.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操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...
随机推荐
- Hexagon HDU - 6862
题目链接:https://vjudge.net/problem/HDU-6862 题意: 由六边形组成的圆形图案,要求不重复走遍历每一个小六边形. 思路:https://www.cnblogs.com ...
- Scientific Internet Access
下载小飞机 https://github.com/shadowsocksr-backup 寻找ssr https://github.com/Alvin9999/new-pac/wiki/ss%E5%8 ...
- 体验用yarp当网关
Yarp是微软开源的一个用.net实现的反向代理工具包,github库就叫reverse-proxy(反向代理)(吐槽一下微软起名字233333) nuget包preview9之前都叫Microsof ...
- 学习Typora来写博客
Typora学习 标题分级 知识详解 标题分级可使用快捷键Ctry+数字键(1.2.3.4.5.6.0) 例如Ctry+1为一级标题,Ctry+2为二级标题,以此类推,总共可分为六个级别的标题,Ctr ...
- 第24 章 : Kubernetes API 编程利器:Operator 和 Operator Framework
Kubernetes API 编程利器:Operator 和 Operator Framework 本节课程主要分享以下三方面的内容: operator 概述 operator framework 实 ...
- Kafka 消息存储机制
Kafka 消息以 Partition 作为存储单元,那么在 Partition 内消息是以什么样的格式存储的呢,如何处理 Partition 中的消息,又有哪些安全策略来保证消息不会丢失呢,这一篇我 ...
- java面试-谈谈你对OOM的理解
一.OOM(OutOfMemoryError): 对象无法释放或无法被垃圾回收,造成内存浪费,导致程序运行速度减慢,甚至系统崩溃等严重后果,就是内存泄漏.多个内存泄漏造成可使用内存变少,会导致内存溢出 ...
- Chrome/Chromium的实验性功能+扩展推荐,让你的Chrome/Chromium起飞!
1 实验性功能 Chrome/Chromium内置了一些很酷的实验性功能,打开 chrome://flags 即可访问.打开这些实验性功能后,浏览器的使用体验会更好,这里Chrome的版本为80.0. ...
- Go-22-方法
方法 Go语言同时有函数和方法,方法的本质是函数,但是方法和函数又有所不同. 函数(function)是一段具有独立功能的代码,可以被反复多次调用,从而实现代码复用. 方法(method)是一个类的行 ...
- Dropping Balls UVA - 679
A number of K balls are dropped one by one from the root of a fully binary tree structure FBT. Eac ...