.NET Core 依赖注入改造(1)- 命名服务

.NET Core 依赖注入改造(1)- 命名服务
.NET Core 依赖注入改造(2)- 委托转换
.NET Core 依赖注入改造(3)- ILogger
.NET Core 依赖注入改造(4)- ActivatorUtilities
.NET Core 依赖注入改造(5)- Context

.NET Core 依赖注入改造(附1)- Autowired

.NET Standard 之后重新定义了一套相对独立和标准的依赖注入框架;
可以在Nuget中搜索 Microsoft.Extensions.DependencyInjection.AbstractionsMicrosoft.Extensions.DependencyInjection
前者是框架的抽象的定义,后者是官方的实现;
这样做的好处是显而易见的,在开发组件时可以安装 Abstractions 按照标准接口、抽象类实现相关功能,不依赖具体实现;
而使用者就可以自由下载任意实现,例如非官方的Autofac.Extensions.DependencyInjection也是一个不错的选择;

更多介绍网上的文章太多,就不展开了

使用nuget安装框架


然后写一个简单的例子


.NET Core 依赖注入改造(1)- 命名服务_第1张图片

emmm,我知道用委托作为服务不是主流的用法,但是,我喜欢。。。

上面的例子中,我从Main方法中注入一个ToJsonStringToXmlString的委托作为一个服务;
然后将ServiceProvider放入上下文;
接着在另一个方法中从上下文获取ServiceProvider,然后分别获取2个服务并使用它们;

.NET Core 依赖注入改造(1)- 命名服务_第2张图片

实际开发中这样使用存在一个问题,注入和使用者都需要引用2个委托类型ToJsonStringToXmlString
而我想使用标准Func时,尴尬的发现它们2个的声明是一毛一样的。

.NET Core 依赖注入改造(1)- 命名服务_第3张图片

如果这样结果无疑是不正确的。

所以我想在有没有可能拓展出一种这样的命名服务

.NET Core 依赖注入改造(1)- 命名服务_第4张图片

在Github上找到了Microsoft.Extensions.DependencyInjection的源码;
找到AddSingleton方法

public static IServiceCollection AddSingleton(
    this IServiceCollection services,
    TService implementationInstance)
    where TService : class
{
    // 一些无关代码
    return services.AddSingleton(typeof(TService), implementationInstance); //这里调用了下面的方法
}

public static IServiceCollection AddSingleton(
    this IServiceCollection services,
    Type serviceType,
    object implementationInstance)
{
    // 一些无关代码
    var serviceDescriptor = new ServiceDescriptor(serviceType, implementationInstance);
    services.Add(serviceDescriptor);
    return services;
}

这里看到了一个 ServiceDescriptor 对象,看名字应该是用来描述注册的服务的信息的;

.NET Core 依赖注入改造(1)- 命名服务_第5张图片

从属性中也能看出,这里描述了 服务实例类型服务声明类型声明周期实例对象实例创建方法
所以估摸着从这里入手 想办法加入 服务名称的属性可以作为突破点。

but,先不着急,先看看获取服务是怎么做的;

这部分比较费时间,不详细展开了,感兴趣的可以自己下载源码之后细细研究;

基本顺序是:

  1. 获取服务是依赖接口 IServiceProvider,所以需要先找到接口实现
  2. 根据 ServiceCollectionContainerBuilderExtensions.BuildServiceProvider方法可以得到实现类是ServiceProvider
  3. ServiceProvider.GetService 中用到了 DynamicServiceProviderEngine
  4. DynamicServiceProviderEngine继承自CompiledServiceProviderEngine
  5. CompiledServiceProviderEngine继承自ServiceProviderEngine
  6. ServiceProviderEngine中用到了ServiceProviderEngineScopeCallSiteExpressionBuilderCallSiteFactory
  7. CallSiteFactory中找到2个关键方法TryCreateOpenGenericTryCreateExact
  8. 最终转了一圈发现,获取服务时,匹配规则就是很单纯的serviceType == ServiceDescriptor.ServiceType 或者对于泛型服务来说serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == ServiceDescriptor.ServiceType

所以结论是,只要干涉 serviceType==操作就可以实现自己获取服务的匹配逻辑;

说干就干,既然是干涉 serviceType ,那么 serviceType 必然是一个自定义对象,自己实现EqualsGetHashCode==
所以接下来就是做一个 NamedType类继承自Type,由于Type是抽象类,需要实现的部分太多了,所以可以继承TypeDelegator来实现

.NET Core 依赖注入改造(1)- 命名服务_第6张图片

拓展方法

.NET Core 依赖注入改造(1)- 命名服务_第7张图片
image.png

现在回到最开始的方法运行下


.NET Core 依赖注入改造(1)- 命名服务_第8张图片

github:https://github.com/blqw/blqw.DI/tree/master/src/blqw.DI.NamedService
nuget:https://www.nuget.org/packages/blqw.DI.NamedService

你可能感兴趣的:(.NET Core 依赖注入改造(1)- 命名服务)