asp.net core 依赖注入实现全过程粗略剖析(1)

2023-10-19 19:26:48 浏览数 (2)

转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/

常用扩展方法 注入依赖服务:

代码语言:javascript复制
new ServiceCollection().AddSingleton<IApplicationBuilder, ApplicationBuilder>();

// AddSingleton多个重载方法 源码

代码语言:javascript复制
public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, TService
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

return services.AddSingleton(typeof(TService), typeof(TImplementation));
}

// Singleton模式 最终的调用
public static IServiceCollection AddSingleton(
this IServiceCollection services,
Type serviceType,
Type implementationType)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

if (serviceType == null)
{
throw new ArgumentNullException(nameof(serviceType));
}

if (implementationType == null)
{
throw new ArgumentNullException(nameof(implementationType));
}

return Add(services, serviceType, implementationType, ServiceLifetime.Singleton);
}

// 所有的Addxxx 最终都是调用Add方法,将ServiceDescriptor添加到IServiceCollection中:
private static IServiceCollection Add(
IServiceCollection collection,
Type serviceType,
Type implementationType,
ServiceLifetime lifetime)
{
var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);
collection.Add(descriptor);
return collection;
}

// IServiceCollection源码:
public interface IServiceCollection : IList<ServiceDescriptor>
{}

如上,我们一般在ConfigureService中使用Addxxx将服务注入框架的过程。大概做个总结,其实就是屌用IServiceCollection的Addxxx 扩展方法,随后调用Add方法,初始化一个ServiceDescriptor,参数是我们注入的接口和类,还有就是生命周期。随后添加到IServiceCollection中,根据该接口的定义就是一个ServiceDescriptor的集合。

我们看看ServiceDescriptor的源码:

代码语言:javascript复制
public ServiceDescriptor( 
 Type serviceType, 
 object instance) 
 : this(serviceType, ServiceLifetime.Singleton) 
{ 
 if (serviceType == null) 
 { 
 throw new ArgumentNullException(nameof(serviceType)); 
 } 
 
 if (instance == null) 
 { 
 throw new ArgumentNullException(nameof(instance)); 
 } 
 
 ImplementationInstance = instance; 
}

该类就是初始化并获取如下属性:

代码语言:javascript复制
/// <inheritdoc />
public ServiceLifetime Lifetime { get; }

/// <inheritdoc />
public Type ServiceType { get; }

/// <inheritdoc />
public Type ImplementationType { get; }

/// <inheritdoc />
public object ImplementationInstance { get; }

/// <inheritdoc />
public Func<IServiceProvider, object> ImplementationFactory { get; }

到此,我们的服务注入到asp.net core框架中就完事了,那么服务的实例化呢?

首先我们理下思路,IServiceProvider接口对应的实现是ServiceProvider,这个类就是实例化了IServiceProvider接口,而IServiceProvider接口只有一个方法:

代码语言:javascript复制
public object GetService(Type serviceType);

该方法就是获取注入的服务。但是ServiceProvider类不单单是获取注入的服务,服务的实例化还是在该类中实现的,我们看下:

代码语言:javascript复制
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback
{
private readonly IServiceProviderEngine _engine;

private readonly CallSiteValidator _callSiteValidator;

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));
}
}

/// <summary>
/// Gets the service object of the specified type.
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public object GetService(Type serviceType) => _engine.GetService(serviceType);

/// <inheritdoc />
public void Dispose() => _engine.Dispose();

void IServiceProviderEngineCallback.OnCreate(IServiceCallSite callSite)
{
_callSiteValidator.ValidateCallSite(callSite);
}

void IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
{
_callSiteValidator.ValidateResolution(serviceType, scope, _engine.RootScope);
}
}

可以看到该类的构造函数中就是实例化服务的过程了。很直白的可以看出我们常见的几种方法来实例化类:反射,Emit,表达式树等...

目前也算是交代清楚了相关的类。那么框架具体是如何来实例化的呢?整个的流程是怎么样的。篇2再叙

源码地址:https://github.com/aspnet/DependencyInjection  

0 人点赞