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. Unity3D入门之Unity3D介绍以及编辑器的使用(1)

    1.Unity3D介绍 Unity3D是跨平台(IOS.Android.Windows Phone.Windows.Flash.XBOX360.PS3.Wii等)游戏引擎,可以开发2D.2.5D.3D ...

  2. node访问iis使用keep-alive设置不当

    iis默认的连接超时时间为2分钟 ,因此node程序使用keep-alive访问时,keep-alive的时间不应该超过2分钟,否则在请求完成后,node端继续保持连接,2分钟后iis断开连接,会导致 ...

  3. [异常解决] ubuntu上安采用sudo启动的firefox,ibus输入法失效问题解决

    采用sudo启动的应用是root权限的应用, ibus失效是因为ibus的初始配置采用user权限: 而root下运行的firefox输入法的配置还是停留在默认情况~ 解决方案是在shell下以roo ...

  4. Java枚举类型getClass和getDeclaringClass区别(未完待续)

    Java中的枚举类型有getClass()和getDeclaringClass()两个方法,在通常情况下这两个方法返回的类型一样,在某些场景下会有不同的表现 参照 http://stackoverfl ...

  5. SWF READER 破解日志。

    网上传闻swf reader是破解最厉害的神器,可以内存抓取+doSWF反编译.所以去官网下了一个: SWF_Reader_2.3 不出所料,demo版本没有反编译的功能.网上搜到一个哥们尝试了下: ...

  6. Windows Live Writer 初次使用

    Windows  Live Writer 博客园文章的一款发布器,这篇文章就是通过其发布的,可以先在word中写好博客内容,直接粘贴到这里发布就OK,之前我都是先在Word中写好一份,然后在blogs ...

  7. redis系列-redis的使用场景

    redis越来越受大家欢迎,提升下速度,做下缓存,完成KPI之利器呀.翻译一篇文章<<How to take advantage of Redis just adding it to yo ...

  8. C struct结构体内存对齐问题

    在空间看到别人的疑问引起了我的兴趣,刚好是我感兴趣的话题,就写一下.为了别人的疑问,也发表在qq空间里.因为下班比较晚,10点才到家,发表的也晚.其实是个简单的问题.  直接用实例和内存图说明: #i ...

  9. jmx完整示例

    很早就开始去了解这个了,不过一直都是皮毛,基本概念明白,具体api几乎一无不知... 认真看了几篇文章,做了测试,终于有所了解 参考 入门级别: http://www.cnblogs.com/agou ...

  10. Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx

    Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx 1.1.  版本历史1 2. 1. 未来版本规划2 2.1. V12版本规划2 2.2. ...