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

依赖注入(DI)不是一个新的话题,它的出现是伴随着系统解耦的需要而几乎必然产生的。

在SOLID设计原则中,DIP(Dependency inversion principle)——依赖倒置,规定了“需依赖抽象,而非实现”的准则,该原则主要目的是通过引入抽象(比如接口)的方式降低模块之间的耦合性。与此原则相拟而又有所不同的是IoC(inversion of control)——控制反转设计原则。这项原则定义了应该由通用框架而非外部代码决定控制流(control flow)的概念。对控制反转的实现有数种技术,DI(Dependency injection)——依赖注入便是其中之一,而依赖注入技术同时又支持依赖倒置的设计原则,所以它被广泛使用并不是件令人意外的事情。

依赖注入的基本特性是借由一个对象提供对另一对象的依赖。这样的一个对象通常又被称为容器。容器负责被依赖对象的注册(register),解析(resolve)与释放(release),并具有将被依赖对象注入到依赖对象内部的功能。

在之前的ASP.NET开发过程中,要想使用到依赖注入技术必需依赖第三方类库,而在ASP.NET Core中,这项技术已经被引入到其自身的框架中。

容器

ASP.NET Core中使用ServiceProvider作为依赖注入的容器,它是在WebHostBuilder类中被引入的。

public IWebHost Build() { ... IServiceProvider GetProviderFromFactory(IServiceCollection collection) { var provider = collection.BuildServiceProvider(); var factory = provider.GetService<IServiceProviderFactory<IServiceCollection>>(); if (factory != null) { using (provider) { return factory.CreateServiceProvider(factory.CreateBuilder(collection)); } } return provider; } } 注册

所需依赖的对象通过ServiceCollectionServiceExtensions中的各种扩展方法被加入到ServiceCollection类中。ServiceCollection类内部维护着一个ServiceDescriptor集合。而ServiceCollection又会被传入ServiceProvider的构造方法。

public static IServiceCollection AddTransient( this IServiceCollection services, Type serviceType, Type implementationType) { ... return Add(services, serviceType, implementationType, ServiceLifetime.Transient); } public static IServiceCollection AddScoped( this IServiceCollection services, Type serviceType, Type implementationType) { ... return Add(services, serviceType, implementationType, ServiceLifetime.Scoped); } public static IServiceCollection AddSingleton( this IServiceCollection services, Type serviceType, Type implementationType) { ... return Add(services, serviceType, implementationType, ServiceLifetime.Singleton); } private static IServiceCollection Add( IServiceCollection collection, Type serviceType, Type implementationType, ServiceLifetime lifetime) { var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime); collection.Add(descriptor); return collection; } 解析

要想获得已注册的对象,可以通过ServiceProviderServiceExtensions类的扩展方法GetService。

public static T GetService<T>(this IServiceProvider provider) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } return (T)provider.GetService(typeof(T)); }

ServiceProvider的GetService方法其实是调用了它内部各种引擎的父类ServiceProviderEngine的方法。这些引擎间区别在于实现方式以及性能上,功能方面都是一样的。默认引擎是DynamicServiceProviderEngine。

private readonly IServiceProviderEngine _engine; internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options) { IServiceProviderEngineCallback callback = null; if (options.ValidateScopes) { callback = this; _callSiteValidator = new CallSiteValidator(); } switch (options.Mode) { case ServiceProviderMode.Dynamic: _engine = new DynamicServiceProviderEngine(serviceDescriptors, callback); break; case ServiceProviderMode.Runtime: _engine = new RuntimeServiceProviderEngine(serviceDescriptors, callback); break; #if IL_EMIT case ServiceProviderMode.ILEmit: _engine = new ILEmitServiceProviderEngine(serviceDescriptors, callback); break; #endif case ServiceProviderMode.Expressions: _engine = new ExpressionsServiceProviderEngine(serviceDescriptors, callback); break; default: throw new NotSupportedException(nameof(options.Mode)); } } public object GetService(Type serviceType) => _engine.GetService(serviceType);

ServiceProviderEngine类的CreateServiceAccessor方法创建了CallSite。

internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) { if (_disposed) { ThrowHelper.ThrowObjectDisposedException(); } var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor); _callback?.OnResolve(serviceType, serviceProviderEngineScope); return realizedService.Invoke(serviceProviderEngineScope); } private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(Type serviceType) { var callSite = CallSiteFactory.CreateCallSite(serviceType, new CallSiteChain()); if (callSite != null) { _callback?.OnCreate(callSite); return RealizeService(callSite); } return _ => null; }

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

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