zoukankan      html  css  js  c++  java
  • asp.net core 依赖注入实现全过程粗略剖析(1)

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

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

    new ServiceCollection().AddSingleton<IApplicationBuilder, ApplicationBuilder>();
    View Code

    // AddSingleton多个重载方法 源码

    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>
    {}
    View Code

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

    我们看看ServiceDescriptor的源码:

    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; 
    }
    View Code

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

    /// <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; }
    View Code

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

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

    public object GetService(Type serviceType);

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

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

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

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

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

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

  • 相关阅读:
    #Python#中国大学生实习-大数据分析
    PHP 数字转大写
    pdo封装2
    python tkinter组件学习
    微信小程序相关资料整理
    php任务管理器 —— Jobby
    linux 定时任务未执行php脚本
    centos中安装php7
    php资源列表
    给二维码(图片)添加文字(水印),让生成的二维码中间带logo
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/9385026.html
Copyright © 2011-2022 走看看