[Asp.net 5] DependencyInjection项目代码分析2-Autofac
Microsoft.Framework.DependencyInjection.Autofac源码分析
该工程只有一个代码静态类AutofacRegistration,但是该类有3个扩展方法,以及3个内部类。扩展方法如下:
public static class AutofacRegistration
{
public static void Populate(this ContainerBuilder builder,IEnumerable<ServiceDescriptor> descriptors); private static void Register(ContainerBuilder builder,IEnumerable<ServiceDescriptor> descriptors); private static IRegistrationBuilder<object, T, U> ConfigureLifecycle<T, U>(this IRegistrationBuilder<object, T, U> registrationBuilder,ServiceLifetime lifecycleKind)
}
在Autofac中,ContainerBuilder是用于类型注册的,3个扩展方法都是基于此展开的。
Populate方法如下:先对IServiceProvider、IServiceScopeFactory接口进行注册,之后调用Register方法,对于外部的具体类型进行注册。该方法的入参是IEnumerable<ServiceDescriptor> descriptors类型,所以参数可以直接使用IServiceCollection(也就是List<ServiceDescriptor>)。
public static void Populate(this ContainerBuilder builder,
IEnumerable<ServiceDescriptor> descriptors)
{
builder.RegisterType<AutofacServiceProvider>().As<IServiceProvider>();
builder.RegisterType<AutofacServiceScopeFactory>().As<IServiceScopeFactory>(); Register(builder, descriptors);
}
对于Register方法相对复杂些,需要将ServiceDescriptor对象转化为实际的注册类型,代码如下所示:
private static void Register(
ContainerBuilder builder,
IEnumerable<ServiceDescriptor> descriptors)
{
foreach (var descriptor in descriptors)
{
if (descriptor.ImplementationType != null)
{
// Test if the an open generic type is being registered
var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
if (serviceTypeInfo.IsGenericTypeDefinition)
{
builder
.RegisterGeneric(descriptor.ImplementationType)
.As(descriptor.ServiceType)
.ConfigureLifecycle(descriptor.Lifetime);
}
else
{
builder
.RegisterType(descriptor.ImplementationType)
.As(descriptor.ServiceType)
.ConfigureLifecycle(descriptor.Lifetime);
}
}
else if (descriptor.ImplementationFactory != null)
{
var registration = RegistrationBuilder.ForDelegate(descriptor.ServiceType, (context, parameters) =>
{
var serviceProvider = context.Resolve<IServiceProvider>();
return descriptor.ImplementationFactory(serviceProvider);
})
.ConfigureLifecycle(descriptor.Lifetime)
.CreateRegistration(); builder.RegisterComponent(registration);
}
else
{
builder
.RegisterInstance(descriptor.ImplementationInstance)
.As(descriptor.ServiceType)
.ConfigureLifecycle(descriptor.Lifetime);
}
}
}
代码看起来挺多,实际也很简单对于列表进行循环遍历,对于每一项:如果注册类型不为空,使用ContainerBuilder的类型注册方法进行注册(包括泛型和非泛型的);如果类型没提供,判断是否为类型提供工厂delegate,如果提供,使用ContainerBuilder注册代理的方式注册;最后都没有直接将实例类型进行注册。在ContainerBuilder中涉及到了ConfigureLifecycle方法,世界该方法仅仅是将DependencyInjection中定义的ServiceLifetime枚举转化为Autofac能够识别的类型。
private static IRegistrationBuilder<object, T, U> ConfigureLifecycle<T, U>(
this IRegistrationBuilder<object, T, U> registrationBuilder,
ServiceLifetime lifecycleKind)
{
switch (lifecycleKind)
{
case ServiceLifetime.Singleton:
registrationBuilder.SingleInstance();
break;
case ServiceLifetime.Scoped:
registrationBuilder.InstancePerLifetimeScope();
break;
case ServiceLifetime.Transient:
registrationBuilder.InstancePerDependency();
break;
} return registrationBuilder;
}
*IRegistrationBuilder是Autofac中对于注入类型范围进行控制的接口
回过头来我们看下AutofacServiceProvider和AutofacServiceScopeFactory类(Populate方法进行的注入实现类)。
AutofacServiceScopeFactory类,实现IServiceScopeFactory接口,并且CreateScope方法创建一个新AutofacServiceScope实例
private class AutofacServiceScopeFactory : IServiceScopeFactory
{
private readonly ILifetimeScope _lifetimeScope; public AutofacServiceScopeFactory(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
} public IServiceScope CreateScope()
{
return new AutofacServiceScope(_lifetimeScope.BeginLifetimeScope());
}
}
AutofacServiceScope类。使用内部ILifetimeScope创建新的IServiceProvider对象。当当前作用域失效时,调用Dispose方法,以释放内部的IServiceProvider对象,保证不同的ILifetimeScope(Scope)的IServiceProvider生成的对象不同。
private class AutofacServiceScope : IServiceScope
{
private readonly ILifetimeScope _lifetimeScope;
private readonly IServiceProvider _serviceProvider; public AutofacServiceScope(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
_serviceProvider = _lifetimeScope.Resolve<IServiceProvider>();
} public IServiceProvider ServiceProvider
{
get { return _serviceProvider; }
} public void Dispose()
{
_lifetimeScope.Dispose();
}
}
AutofacServiceProvider类用于创建具体的对象。代码如下。IComponentContext参数会在Aotufac注入实例化时自动初始化。
private class AutofacServiceProvider : IServiceProvider
{
private readonly IComponentContext _componentContext; public AutofacServiceProvider(IComponentContext componentContext)
{
_componentContext = componentContext;
} public object GetService(Type serviceType)
{
return _componentContext.ResolveOptional(serviceType);
}
}
[Asp.net 5] DependencyInjection项目代码分析2-Autofac的更多相关文章
- [Asp.net 5] DependencyInjection项目代码分析-目录
微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)
Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(3)
这个系列已经写了5篇,链接地址如下: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Auto ...
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(4)
这个系列已经写了6篇,链接地址如下: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Auto ...
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(2)
在 DependencyInjection项目代码分析4-微软的实现(1)中介绍了“ServiceTable”.“ServiceEntry”.“IGenericService”.“IService”. ...
- [Asp.net 5] DependencyInjection项目代码分析
最近在研究开源代码,正好发现Asp.net5的源码,下载地址:https://github.com/aspnet. 今天主要讲的是DependencyInjection这部分,抛砖引玉,供大家参考,也 ...
- [Asp.net 5] DependencyInjection项目代码分析3-Ninject
Microsoft.Framework.DependencyInjection.Ninject 该工程内部共包含5个类文件,底层使用Ninject实现依赖注入,工程截图如下: 从文件命名可以看出,Ni ...
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(1)
前面俩种实现中,很多内部细节都无法知道,微软的框架也是为了屏蔽具体实现,只让我们关注接口.但是人都是充满好奇的,依赖注入到底是怎么实现的呢? 微软又有怎样的实现呢?下面就为大家一一呈现(说实话,代码真 ...
- Jenkins+Gradle+Sonar进行Java项目代码分析
Jenkins+Maven+Sonar与Jenkins+Gradle+Sonar配置方法很相似,区别就是Java项目所用的编译工具不同,一个是maven,一个是gradle 使用maven编译工具的可 ...
随机推荐
- 新版markdown功能发布!支持github flavored markdown!
让大家久等了!新版markdown功能一直拖到今天才发布,很是愧疚...但不管怎么样,总算发布了! 今年1月份发布第一版markdown功能之后,很多园友反馈说做得很烂,我们综合大家的反馈之后发现不仅 ...
- [硬件项目] 2、汽车倒车雷达设计——基于专用倒车雷达芯片GM3101的设计方案与采用CX20106A红外线检测芯片方案对比
前言 尽管每辆汽车都有后视镜,但不可避免地都存在一个后视镜的盲区,倒车雷达则可一定程度帮助驾驶员扫除视野死角和视线模糊的缺陷,提高驾驶安全性.上一节已经分析清倒车雷达的语音模块(上一节),本节将深入分 ...
- http学习笔记(二)—— 嘿!伙计,你在哪?(URL)
我们之所以希望浏览网页,其中一个重要的原因就是庞大的web世界中有很丰富的资源,他就像哆啦a梦的口袋,随时都能拿出我们想要的宝贝.这些资源通过http被传送到我们的浏览器,并展示到我们的屏幕上.而我们 ...
- zk系列-zookeeper的使用
zk支持java/c访问,java常用的有apache-zkclient.社区版的i0tec-zkclient.github.adyliu,apache-zkclient是zk自身提供的接口,i0te ...
- MVVM架构~knockoutjs系列之数组的$index和$data
返回目录 已经写了很多knockoutjs的文章了,今天在review代码时,忽然看到一个问题,在knockout环境下,如何遍历一个简单的数组?对于遍历对象组件的数组来说,很容易,直接foreach ...
- Excel快速改变行列的次序
改变行列次序是在Excel中常常需要进行的操作,多数用户的方法是先剪切要调整的行或列,然后选定目标位置,单击菜单“插入”→“剪切单元格”. 事实上,使用键盘来配合的话,改变行列的次序可以更快捷.比 ...
- Android开发学习之路-使用Handler和Message更新UI
在Android中,在非主线程中更新UI控件是不安全的,app在运行时会直接Crash,所以当我们需要在非主线程中更新UI控件,那么就需要用到Handler和Message来实现 Demo中,使用到一 ...
- 每天一个linux命令(36):diff 命令
diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的 ...
- IBM appscan 9.0破解版分享
简介:IBM AppScan该产品是一个领先的 Web 应用安全测试工具,曾以 Watchfire AppScan 的名称享誉业界.Rational AppScan 可自动化 Web 应用的安全漏洞评 ...
- 【QQ技术】群文件报毒怎样下载?~ 变相绕过QQ复杂检验过程
刚才又人问我,要是群文件被鉴定为病毒那怎么下载? 我简单说一下吧: 其实qq客户端过滤比较严的,而web段却还是老一套,很多人说出现这个情况其实是腾讯已经把他库里面的文件删了,其实不然 如果源删了,那 ...