欢迎来到 IT实训基地-南通科迅教育
咨询电话:0513-81107100
.NET Core 依赖注入改造(1)- 命名服务
2018/9/29
科迅教育
903
南通Java培训学校哪里好

一、

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

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

二、

使用nuget安装框架

net图片1.jpg

然后写一个简单的例子

net图片2.jpg

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

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

net图片3.jpg

三、

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

net图片4.jpg

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

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

net图片5.jpg


四、

在Github上找到了Microsoft.Extensions.DependencyInjection的源码

找到AddSingleton方法

public static IServiceCollection AddSingleton<TService>(

    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图片6.jpg


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

五、

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

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

基本顺序是:

1. 获取服务是依赖接口 IServiceProvider,所以需要先找到接口实现

2. 根据 ServiceCollectionContainerBuilderExtensions.BuildServiceProvider方法可以得到实现类是ServiceProvider 

3. ServiceProvider.GetService 中用到了 DynamicServiceProviderEngine 

4. DynamicServiceProviderEngine继承自CompiledServiceProviderEngine 

5. CompiledServiceProviderEngine继承自ServiceProviderEngine 

6. ServiceProviderEngine中用到了ServiceProviderEngineScope,CallSiteExpressionBuilder,CallSiteFactory 

7. 在CallSiteFactory中找到2个关键方法TryCreateOpenGeneric和TryCreateExact 

8. 最终转了一圈发现,获取服务时,匹配规则就是很单纯的serviceType == ServiceDescriptor.ServiceType 或者对于泛型服务来说serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == ServiceDescriptor.ServiceType 

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

六、

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

net图片7.jpg

拓展方法

net图片8.jpg

七、

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

net图片9.jpg




77
关闭
先学习,后交费申请表
每期5位名额
在线咨询
免费电话
QQ联系
先学习,后交费
TOP
您好,您想咨询哪门课程呢?
关于我们
机构简介
官方资讯
地理位置
联系我们
0513-91107100
周一至周六     8:30-21:00
微信扫我送教程
手机端访问
南通科迅教育信息咨询有限公司     苏ICP备15009282号     联系地址:江苏省南通市人民中路23-6号新亚大厦三楼             法律顾问:江苏瑞慈律师事务所     Copyright 2008-