.NET Core开发日志——依赖注入 (3)

在ServiceProviderEngineScope类内部有着用于释放资源的Dispose方法。

public void Dispose() { lock (ResolvedServices) { if (_disposed) { return; } _disposed = true; if (_disposables != null) { for (var i = _disposables.Count - 1; i >= 0; i--) { var disposable = _disposables[i]; disposable.Dispose(); } _disposables.Clear(); } ResolvedServices.Clear(); } } internal object CaptureDisposable(object service) { _captureDisposableCallback?.Invoke(service); if (!ReferenceEquals(this, service)) { if (service is IDisposable disposable) { lock (ResolvedServices) { if (_disposables == null) { _disposables = new List<IDisposable>(); } _disposables.Add(disposable); } } } return service; }

并不是所有对象都会通过ServiceProvider容器释放资源,只有容器自己创建的才可以。如果是新建对象再传入容器,容器不会为其作处理。

public void ConfigureServices(IServiceCollection services) { // 容器创建了实例所以会释放它。 services.AddScoped<Service1>(); services.AddSingleton<Service2>(); services.AddSingleton<ISomeService>(sp => new SomeServiceImplementation()); // 容器没有创建实例所以不会释放它。 services.AddSingleton<Service3>(new Service3()); services.AddSingleton(new Service3()); } 注入

ASP.NET Core中最常用的是Constructor Inject(构造器注入)方式。在其MVC框架中,通过DefaultControllerActivator生成Controller时,就可以跟踪到依赖注入是如何被其使用的。

public virtual object Create(ControllerContext controllerContext) { ... var serviceProvider = controllerContext.HttpContext.RequestServices; return _typeActivatorCache.CreateInstance<object>(serviceProvider, controllerTypeInfo.AsType()); }

DefaultControllerActivator的Create方法使用了TypeActivatorCache类,其内部用到了ActivatorUtilities.CreateFactory方法。

public class TypeActivatorCache : ITypeActivatorCache { private readonly Func<Type, ObjectFactory> _createFactory = (type) => ActivatorUtilities.CreateFactory(type, Type.EmptyTypes); private readonly ConcurrentDictionary<Type, ObjectFactory> _typeActivatorCache = new ConcurrentDictionary<Type, ObjectFactory>(); public TInstance CreateInstance<TInstance>( IServiceProvider serviceProvider, Type implementationType) { ... var createFactory = _typeActivatorCache.GetOrAdd(implementationType, _createFactory); return (TInstance)createFactory(serviceProvider, arguments: null); } }

ActivatorUtilities类位于ServiceProvider同样的程序集中。

public static ObjectFactory CreateFactory(Type instanceType, Type[] argumentTypes) { FindApplicableConstructor(instanceType, argumentTypes, out ConstructorInfo constructor, out int?[] parameterMap); var provider = Expression.Parameter(typeof(IServiceProvider), "provider"); var argumentArray = Expression.Parameter(typeof(object[]), "argumentArray"); var factoryExpressionBody = BuildFactoryExpression(constructor, parameterMap, provider, argumentArray); var factoryLamda = Expression.Lambda<Func<IServiceProvider, object[], object>>( factoryExpressionBody, provider, argumentArray); var result = factoryLamda.Compile(); return result.Invoke; }

留意BuildFactoryExpression方法中GetServiceInfo变量。

private static Expression BuildFactoryExpression( ConstructorInfo constructor, int?[] parameterMap, Expression serviceProvider, Expression factoryArgumentArray) { var constructorParameters = constructor.GetParameters(); var constructorArguments = new Expression[constructorParameters.Length]; for (var i = 0; i < constructorParameters.Length; i++) { var constructorParameter = constructorParameters[i]; var parameterType = constructorParameter.ParameterType; var hasDefaultValue = ParameterDefaultValue.TryGetDefaultValue(constructorParameter, out var defaultValue); if (parameterMap[i] != null) { constructorArguments[i] = Expression.ArrayAccess(factoryArgumentArray, Expression.Constant(parameterMap[i])); } else { var parameterTypeExpression = new Expression[] { serviceProvider, Expression.Constant(parameterType, typeof(Type)), Expression.Constant(constructor.DeclaringType, typeof(Type)), Expression.Constant(hasDefaultValue) }; constructorArguments[i] = Expression.Call(GetServiceInfo, parameterTypeExpression); } ... } return Expression.New(constructor, constructorArguments); }

GetServiceInfo变量申明了对GetService方法的调用,而此GetService其实正是对ServiceProvider的调用。

private static readonly MethodInfo GetServiceInfo = GetMethodInfo<Func<IServiceProvider, Type, Type, bool, object>>((sp, t, r, c) => GetService(sp, t, r, c)); private static object GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired) { var service = sp.GetService(type); ... return service; }

通过以上的处理,在创建Controller时,其构造方法中所需参数的类型也会被容器解析,创建相应实例,从而实现依赖注入功能。

生命周期

ASP.NET Core容器可以创建三种生命周期的对象:

Transient, 每次取得的都是新的对象。

Scoped, 每次ASP.NET请求生成不同的对象。

Singleton,同一对象只会生成一次。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydzfw.html