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的更多相关文章

  1. [Asp.net 5] DependencyInjection项目代码分析-目录

    微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...

  2. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)

    Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...

  3. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(3)

    这个系列已经写了5篇,链接地址如下: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Auto ...

  4. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(4)

    这个系列已经写了6篇,链接地址如下: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Auto ...

  5. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(2)

    在 DependencyInjection项目代码分析4-微软的实现(1)中介绍了“ServiceTable”.“ServiceEntry”.“IGenericService”.“IService”. ...

  6. [Asp.net 5] DependencyInjection项目代码分析

    最近在研究开源代码,正好发现Asp.net5的源码,下载地址:https://github.com/aspnet. 今天主要讲的是DependencyInjection这部分,抛砖引玉,供大家参考,也 ...

  7. [Asp.net 5] DependencyInjection项目代码分析3-Ninject

    Microsoft.Framework.DependencyInjection.Ninject 该工程内部共包含5个类文件,底层使用Ninject实现依赖注入,工程截图如下: 从文件命名可以看出,Ni ...

  8. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(1)

    前面俩种实现中,很多内部细节都无法知道,微软的框架也是为了屏蔽具体实现,只让我们关注接口.但是人都是充满好奇的,依赖注入到底是怎么实现的呢? 微软又有怎样的实现呢?下面就为大家一一呈现(说实话,代码真 ...

  9. Jenkins+Gradle+Sonar进行Java项目代码分析

    Jenkins+Maven+Sonar与Jenkins+Gradle+Sonar配置方法很相似,区别就是Java项目所用的编译工具不同,一个是maven,一个是gradle 使用maven编译工具的可 ...

随机推荐

  1. var与this,{}与function 小记

    JavaScript var是用来定义一个变量,this常用来定义或调用一个属性或方法.但是在全局范围内,this和var定义变量是等价的. window console.log('window:', ...

  2. 一天一小段js代码(no.2)

    (一)可以用下面js代码来检测弹出窗口是否被屏蔽: var blocked = false ; try { /*window.open()方法接受4个参数window.open(要加载的url,窗口目 ...

  3. windows 8.1 试用感受:蛋疼感大幅降低

    众所周知windows 8 的最大使用感受就是蛋疼. 无论是微软MVP,还是我这样的万年不悔微软小白鼠,普通用户,小白用户,或多或少的都对这款操作系统感到蛋疼. 槽点太多,以至于大家都懒得批判了.好在 ...

  4. save与persist差别

    唯一差别: 在没提交事务情况下 save会产生insert语句,然后因为没提交事务进行回滚. 而这种情况,persist是连insert语句都不会产生.

  5. 第1讲 Redis部署与基本操作

    目录 一.简介 二.安装 1.默认安装位置 2.指定安装位置 3.安装的可执行文件的作用 三.启动与关闭 四.配置文件 五.Redis的数据类型 1. 共计5种类型 2. String(子串类型) 3 ...

  6. [Java面试一]面试复习大纲.

    一.Java基础部分 (搞定所有技术之后才考虑复习的技术点) 1.数组中的排序问题(笔试或者机试,前者可能性更大) 2.面向对象的理解 3.集合相关的问题,比如hashmap跟hashtable的区别 ...

  7. poi 输出Excel显示内容

    在业务系统中多少回接触到Excel解析.在java开发平台下选择 Apache POI是一个非常明智的选择,POI提供非常完善API来读取或写入Microsoft Office Excel. 目前对导 ...

  8. ASP.NET MVC删除数据

    Index.cshtml @model IEnumerable<MvcExample.Models.Category> <script type="text/javascr ...

  9. 【WP 8.1开发】如何处理摄像头翻转的问题

    模拟器就像我们儿时的梦境,在其上运行应用程序时,一切总是那么美好的:而真机测试如同我们这个纷乱无章的现实世界,你会遇到各种小人和畜生,常常会遭受莫名的挫折.面对挫折,有人迎难而上,或不予理采,走自己的 ...

  10. 深入理解PHP内核(六)函数的定义、传参及返回值

    一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) { echo $var; } 1.词法分析 在Zend/zend_language_scann ...