您的位置:首页 > 编程语言 > ASP

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(4)

2015-05-24 14:31 489 查看
这个系列已经写了6篇,链接地址如下:

[Asp.net 5] DependencyInjection项目代码分析

[Asp.net 5] DependencyInjection项目代码分析2-Autofac

[Asp.net 5] DependencyInjection项目代码分析3-Ninject

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(1)

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(2)

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(3)

如果想对本篇有个更好的了解,建议需要先看

[Asp.net 5] DependencyInjection项目代码分析

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(1)

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(2)”。

"[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(3)"

继续[b][b]ServiceProvider类[/b][/b]

在之前的讲解中我们提到过Service类调用CreateCallSite方法时会递归调用,但是我们没具体说明如何递归调的。实际上Service类,通过反射创建实例的时候,会实例化的参数对象,而实例话参数对象通过[b]ServiceProvider[/b]类创建,而[b]ServiceProvider[/b]类创建参数的实例,又需要通过Service类(如果是通过Type注册的)创建。下面我们把Service的CreateInstanceCallSite方法以及[b]ServiceProvider[/b]相关的方法列出来。

private class EmptyIEnumerableCallSite : IServiceCallSite
{
private readonly object _serviceInstance;
private readonly Type _serviceType;

public EmptyIEnumerableCallSite(Type serviceType, object serviceInstance)
{
_serviceType = serviceType;
_serviceInstance = serviceInstance;
}

public object Invoke(ServiceProvider provider)
{
return _serviceInstance;
}

public Expression Build(Expression provider)
{
return Expression.Constant(_serviceInstance, _serviceType);
}
}

private class TransientCallSite : IServiceCallSite
{
private readonly IServiceCallSite _service;

public TransientCallSite(IServiceCallSite service)
{
_service = service;
}

public object Invoke(ServiceProvider provider)
{
return provider.CaptureDisposable(_service.Invoke(provider));
}

public Expression Build(Expression provider)
{
return Expression.Call(
provider,
CaptureDisposableMethodInfo,
_service.Build(provider));
}
}

private class ScopedCallSite : IServiceCallSite
{
private readonly IService _key;
private readonly IServiceCallSite _serviceCallSite;

public ScopedCallSite(IService key, IServiceCallSite serviceCallSite)
{
_key = key;
_serviceCallSite = serviceCallSite;
}

public virtual object Invoke(ServiceProvider provider)
{
object resolved;
lock (provider._sync)
{
if (!provider._resolvedServices.TryGetValue(_key, out resolved))
{
resolved = provider.CaptureDisposable(_serviceCallSite.Invoke(provider));
provider._resolvedServices.Add(_key, resolved);
}
}
return resolved;
}

public virtual Expression Build(Expression providerExpression)
{
var keyExpression = Expression.Constant(
_key,
typeof(IService));

var resolvedExpression = Expression.Variable(typeof(object), "resolved");

var resolvedServicesExpression = Expression.Field(
providerExpression,
"_resolvedServices");

var tryGetValueExpression = Expression.Call(
resolvedServicesExpression,
TryGetValueMethodInfo,
keyExpression,
resolvedExpression);

var captureDisposableExpression = Expression.Assign(
resolvedExpression,
Expression.Call(
providerExpression,
CaptureDisposableMethodInfo,
_serviceCallSite.Build(providerExpression)));

var addValueExpression = Expression.Call(
resolvedServicesExpression,
AddMethodInfo,
keyExpression,
resolvedExpression);

var blockExpression = Expression.Block(
typeof(object),
new[] { resolvedExpression },
Expression.IfThen(
Expression.Not(tryGetValueExpression),
Expression.Block(captureDisposableExpression, addValueExpression)),
resolvedExpression);

return Lock(providerExpression, blockExpression);
}

private static Expression Lock(Expression providerExpression, Expression body)
{
// The C# compiler would copy the lock object to guard against mutation.
// We don't, since we know the lock object is readonly.
var syncField = Expression.Field(providerExpression, "_sync");
var lockWasTaken = Expression.Variable(typeof(bool), "lockWasTaken");

var monitorEnter = Expression.Call(MonitorEnterMethodInfo, syncField, lockWasTaken);
var monitorExit = Expression.Call(MonitorExitMethodInfo, syncField);

var tryBody = Expression.Block(monitorEnter, body);
var finallyBody = Expression.IfThen(lockWasTaken, monitorExit);

return Expression.Block(
typeof(object),
new[] { lockWasTaken },
Expression.TryFinally(tryBody, finallyBody));
}
}

private class SingletonCallSite : ScopedCallSite
{
public SingletonCallSite(IService key, IServiceCallSite serviceCallSite) : base(key, serviceCallSite)
{
}

public override object Invoke(ServiceProvider provider)
{
return base.Invoke(provider._root);
}

public override Expression Build(Expression provider)
{
return base.Build(Expression.Field(provider, "_root"));
}
}


View Code
该工程所有类的关系图(包括内部类以及一些接口),如下所示:



补充说明

IServiceCallSite中定义了Build方法,该方法使用了Expression,但是该篇文章没有对其进行具体的研究,并且Build方法是相对独立的。

对于OpenIEnumerableService泛型省略详解。

示例测试代码:

public static class TestServices
{
public static IServiceCollection DefaultServices()
{
var services = new ServiceCollection();

services.AddTransient<IFakeService, FakeService>();
services.AddTransient<IFakeMultipleService, FakeOneMultipleService>();
services.AddTransient<IFakeMultipleService, FakeTwoMultipleService>();
services.AddTransient<IFakeOuterService, FakeOuterService>();
services.AddInstance<IFakeServiceInstance>(new FakeService() { Message = "Instance" });
services.AddScoped<IFakeScopedService, FakeService>();
services.AddSingleton<IFakeSingletonService, FakeService>();
services.AddTransient<IDependOnNonexistentService, DependOnNonexistentService>();
services.AddTransient<IFakeOpenGenericService<string>, FakeService>();
services.AddTransient(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));

services.AddTransient<IFactoryService>(provider =>
{
var fakeService = provider.GetService<IFakeService>();
return new TransientFactoryService
{
FakeService = fakeService,
Value = 42
};
});

services.AddScoped(provider =>
{
var fakeService = provider.GetService<IFakeService>();
return new ScopedFactoryService
{
FakeService = fakeService,
};
});

services.AddTransient<ServiceAcceptingFactoryService, ServiceAcceptingFactoryService>();
return services;
}
}

public class ServiceProviderContainerTests : ScopingContainerTestBase
{
protected override IServiceProvider CreateContainer()
{
return TestServices.DefaultServices().BuildServiceProvider();
}

[Fact]
public void ScopedServiceCanBeResolved()
{
IServiceProvider container = CreateContainer();

var scopeFactory = container.GetService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var containerScopedService = container.GetService<IFakeScopedService>();
var scopedService1 = scope.ServiceProvider.GetService<IFakeScopedService>();
Thread.Sleep(200);
var scopedService2 = scope.ServiceProvider.GetService<IFakeScopedService>();

Assert.NotEqual(containerScopedService, scopedService1);
Assert.Equal(scopedService1, scopedService2);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: