.NET Core 中依赖注入框架详解 Autofac
本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的
Autofac相比.NET Core原生的注入方式提供了强大的功能,详细可以查看Autofac官方API
(1)首先看第一个例子 控制台应用(.NET Core)
通过Nuget安装两个包 => Autofac Autofac.Extensions.DependencyInjection

public static class Demo
{
public interface IAccount { }
public interface IMessage { }
public interface ITool { }
public class Base : IDisposable
{
public Base()
{
Console.WriteLine($"{GetType().Name} Created");
} public void Dispose()
{
Console.WriteLine($"{GetType().Name} Disposed");
}
}
public class Account : Base, IAccount { }
public class Message : Base, IMessage { }
public class Tool : Base, ITool { } public static void Run()
{
//.NET Core 服务集合
var serviceCollection = new ServiceCollection()
.AddTransient<IAccount, Account>()
.AddTransient<IMessage, Message>(); var containerBuilder = new ContainerBuilder();
//将服务集合添加到Autofac
containerBuilder.Populate(serviceCollection);
//通过类型注册将服务添加到Autofac
containerBuilder.RegisterType().As(); var container = containerBuilder.Build();
IServiceProvider provider = new AutofacServiceProvider(container);
Debug.Assert(provider.GetService() is Account); }
}
- 可以看到程序中 实例化一个Autofac的ContainerBuilder,通过Populate方法遍历传入的服务集合并添加到Autofac的容器中;
- RegisterType是通过类型注册将服务添加到Autofac的容器,如果RegisterType和Populate调换加载顺序,则Populate会覆盖RegisterType的服务集合;
- ContainerBuilder调用Build方法返回的是IContainer对象,该对象实现了ILifetimeScope接口;
- 在创建AutofacServiceProvider(ILifetimeScope lifetimeScope)返回的是AutofacServiceProvider实现了IServiceProvide,可以和.NET Core 的ServiceProvider一样调用GetService创建服务实例
那么使用Autofac有哪些其它优势?下面看看 属性注入和程序集注入

public static class Demo
{
public interface IAccount { }
public interface IMessage { }
public interface ITool { }
public interface ITest { public IMessage Message { get; set; } } public class Base
{
public Base()
{
Console.WriteLine($"{GetType().Name} Created");
} }
public class Account : Base, IAccount { }
public class Message : Base, IMessage { }
public class Tool : Base, ITool { }
public class Test : Base, ITest
{
public IMessage Message { get; set; }
public Test(IAccount account, ITool tool)
{
Console.WriteLine($"Ctor : Test(IAccount, ITool)");
}
} public static void Run()
{
//.NET Core 服务集合
//var serviceCollection = new ServiceCollection()
// .AddTransient<ITool, Tool>(); var containerBuilder = new ContainerBuilder();
//将服务集合添加到Autofac
//containerBuilder.Populate(serviceCollection);
//属性注入
containerBuilder.RegisterType<Test>().As<ITest>().PropertiesAutowired();
//程序集注入
containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.BaseType == typeof(Base))
.As(t => t.GetInterfaces()[0])//调用As方法,暴露服务
.InstancePerLifetimeScope();//每个生命周期作用域的组件在每个嵌套的生命周期作用域中最多只会有一个单一实例 var container = containerBuilder.Build();
IServiceProvider provider = new AutofacServiceProvider(container);
Debug.Assert(provider.GetService<IAccount>() is Account);
Debug.Assert(provider.GetService<IMessage>() is Message);
Debug.Assert(provider.GetService<ITool>() is Tool); var test = provider.GetService<ITest>();
Debug.Assert(test.Message is Message); }
- 属性注入,<code>containerBuilder.RegisterType<Test>().As<ITest>().PropertiesAutowired()</code> 通过PropertiesAutowired 反射方式
- 程序集注册,获取当前所在程序集Assembly.GetExecutingAssembly(),查找所有基类为Base的Type,调用As暴露服务,InstancePerLifetimeScope 为每个实例创建作用域的生命周期
(2)ASP.NET Core 内置DI 与 Autofac 比较

public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddTransient<IAccount, Account>();
}
内置DI 在Startup类 ConfigureServices通过AddTransient方式注册

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory());

Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
//services.AddTransient<IAccount, Account>();//内置DI
} public void ConfigContainer(ContainerBuilder containerBuilder)
{
//containerBuilder.RegisterType<Account>().As<IAccount>();
var assembly = Assembly.GetEntryAssembly();
containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.BaseType == typeof(Base))
.As(t => t.GetInterfaces()[0])
.InstancePerLifetimeScope(); }
Autofac 需要在Program.cs中替换 .NET Core的默认容器 UseServiceProviderFactory(new AutofacServiceProviderFactory())
在 Startup.cs 中 创建ConfigContainer方法,服务注册和 控制台应用相似;
真正在实际项目中按照以上方式注册服务会很麻烦,难以维护,可读性差;Autofac提供了一种以模块化方式进行注册
比如我们有不同的业务模块 AModule BModule...,将这些module继承 Autofac.Module 重写Load方法进行服务注册
最后在ConfigContainer中RegisterModule进行模块化注册
public class AModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
var containerBaseType = typeof(ControllerBase); builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => containerBaseType.IsAssignableFrom(t) && t != containerBaseType)
.PropertiesAutowired();
}
} public void ConfigContainer(ContainerBuilder containerBuilder)
{ containerBuilder.RegisterModule<AModule>(); }
.NET Core 中依赖注入框架详解 Autofac的更多相关文章
- Net Core中数据库事务隔离详解——以Dapper和Mysql为例
Net Core中数据库事务隔离详解--以Dapper和Mysql为例 事务隔离级别 准备工作 Read uncommitted 读未提交 Read committed 读取提交内容 Repeatab ...
- 跟着阿里p7一起学java高并发 - 第19天:JUC中的Executor框架详解1,全面掌握java并发核心技术
这是java高并发系列第19篇文章. 本文主要内容 介绍Executor框架相关内容 介绍Executor 介绍ExecutorService 介绍线程池ThreadPoolExecutor及案例 介 ...
- java高并发系列 - 第20天:JUC中的Executor框架详解2之ExecutorCompletionService
这是java高并发系列第20篇文章. 本文内容 ExecutorCompletionService出现的背景 介绍CompletionService接口及常用的方法 介绍ExecutorComplet ...
- Unity依赖注入使用详解
写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...
- 用工厂模式解决ASP.NET Core中依赖注入的一个烦恼
这是最近在实际开发中遇到的一个问题,用 asp.net core 开发一个后端 web api ,根据指定的 key 清除 2 台 memcached 服务器上的缓存.背景是我们在进行 .net co ...
- .Net Core中依赖注入服务使用总结
一.依赖注入 引入依赖注入的目的是为了解耦和.说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用.这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将 ...
- SpringDI四种依赖注入方式详解
文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! LOGO SpringDI(依赖注入) 一.DI概述 De ...
- Spring 依赖注入方式详解
平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...
- AngularJS开发指南10:AngularJS依赖注入的详解
依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...
随机推荐
- CSS轮廓和圆角
1 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset=" ...
- Lambda 表达式(使用前提、“类型推断”、作用、优缺点、Lambda还能省略的情况)
Lambda 表达式(使用前提."类型推断".作用.优缺点.Lambda还能省略的情况) 1.Lambda使用前提: (1)使用Lambda必须有接口,且接口只有一个抽象方法(即函 ...
- D8016 “/ZI”和“/Gy-”命令行选项不兼容
老版本vs项目升级到vs2017后遇到编译报错: /ZI选项在: /Gy- 选项在: 修改'/ZI'选项为'无' 或者 '/Gy-' 修改为'/Gy'
- D. 【例题4】字符串环
解析 字符串的操作,可以用函数解决这个问题 s 2. f i n d ( s 1. s u b s t r ( i , j ) ) s2.find~(s1.substr~(i,~j)) s2.find ...
- 关于MySQL日志,我与阿里P9都聊了些啥?
写在前面 周末,我与阿里P9资深技术专家(这里就不说名字了),聊起了MySQL这个话题,为啥会聊这个呢?因为他看到我出版了一部<MySQL技术大全:开发.优化与运维实战>,对书籍的评价也是 ...
- UML相关汇总
类图 类图是UML最常用的图之一,用于描述面向对象程序设计中,类.接口等结构之间的关系,如图 类图中涉及到以下几种类型的对象 UMLClass 如图中Class1,代表类 UMLOperation 如 ...
- java7与java9中的try-finally关闭资源
1.java7中的try 在java7之前,对于一些需要使用finally关闭资源的操作,会显得很臃肿. try { // } catch(Exception e) { // } finally { ...
- S-Trees UVA - 712
A Strange Tree (S-tree) over the variable set Xn = {x1,x2,...,xn} is a binary tree representing a ...
- Flowable中的Service
前言 在学习博客[(https://blog.csdn.net/puhaiyang/article/details/79845248)]时,注意到Flowable中的各种Service(如下),进而在 ...
- CentOS7 基本概念以及安装注意事项
什么是Linux发行版?发行版是什么意思? Linux本质上是操作系统内核,类似Chrome浏览器内核一样,Linux发行版CentOS.Redhat.Ubuntu等等都是基于Linux内核开发出来的 ...