本文将通过演示一个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的更多相关文章

  1. Net Core中数据库事务隔离详解——以Dapper和Mysql为例

    Net Core中数据库事务隔离详解--以Dapper和Mysql为例 事务隔离级别 准备工作 Read uncommitted 读未提交 Read committed 读取提交内容 Repeatab ...

  2. 跟着阿里p7一起学java高并发 - 第19天:JUC中的Executor框架详解1,全面掌握java并发核心技术

    这是java高并发系列第19篇文章. 本文主要内容 介绍Executor框架相关内容 介绍Executor 介绍ExecutorService 介绍线程池ThreadPoolExecutor及案例 介 ...

  3. java高并发系列 - 第20天:JUC中的Executor框架详解2之ExecutorCompletionService

    这是java高并发系列第20篇文章. 本文内容 ExecutorCompletionService出现的背景 介绍CompletionService接口及常用的方法 介绍ExecutorComplet ...

  4. Unity依赖注入使用详解

    写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...

  5. 用工厂模式解决ASP.NET Core中依赖注入的一个烦恼

    这是最近在实际开发中遇到的一个问题,用 asp.net core 开发一个后端 web api ,根据指定的 key 清除 2 台 memcached 服务器上的缓存.背景是我们在进行 .net co ...

  6. .Net Core中依赖注入服务使用总结

    一.依赖注入 引入依赖注入的目的是为了解耦和.说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用.这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将 ...

  7. SpringDI四种依赖注入方式详解

    文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! LOGO SpringDI(依赖注入) 一.DI概述 De ...

  8. Spring 依赖注入方式详解

    平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...

  9. AngularJS开发指南10:AngularJS依赖注入的详解

    依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...

随机推荐

  1. Codeforces 1015E1 Stars Drawing (Easy Edition)

    题面: 传送门 题目描述: 要求用十字星星来画题目给出的"星"图.如果不能用十字星星来画"星"图,输出-1:如果能,则输出要在图的哪个位置画相应大小的十字星图. ...

  2. P1426 小鱼会有危险吗(JAVA语言)

    题目描述 有一次,小鱼要从A处沿直线往右边游,小鱼第一秒可以游7米,从第二秒开始每秒游的距离只有前一秒的98%.有个极其邪恶的猎人在距离A处右边s米的地方,安装了一个隐蔽的探测器,探测器左右x米之内是 ...

  3. 如何在Google Web Toolkit环境下Getshell

    出品|MS08067实验室(www.ms08067.com) 本文作者:大盗贼卡卡 Google Web Toolkit简称(GWT),是一款开源Java软件开发框架.今天这篇文章会介绍如何在这样的环 ...

  4. Elasticsearch 基础介绍

    # Elasticsearch简介 ## 基础概念 ​ Elasticsearch由Shay banon在2004年进行初步开发,并且在2010年2月发布第一个版本. ​ 此后Shay banon在2 ...

  5. Clang Static Analyzer-使用手册-编写Checker框架

    Clang Static Analyzer-使用手册-编写Checker Checker是这个工具的灵魂 有了checker才可以检查你的代码 相当于就是CSA通过checker定义的检查方法去检查代 ...

  6. 幻灯片放映模式切换windows terminal背景图片

    目录 幻灯片放映模式切换windows terminal背景图片 脚本功能 开发需求 使用技术 操作说明 使用示例 查看帮助 输入参数使用 脚本详情 引用参考 幻灯片放映模式切换windows ter ...

  7. AI数学基础之:确定图灵机和非确定图灵机

    目录 简介 图灵机 图灵机的缺点 等效图灵机 确定图灵机 非确定图灵机 简介 图灵机是由艾伦·麦席森·图灵在1936年描述的一种抽象机器,它是人们使用纸笔进行数学运算的过程的抽象,它肯定了计算机实现的 ...

  8. 【笔记】《Redis设计与实现》chapter13 客户端

    服务器为每个客户端建立相应的redis.h/redisClient结构,这个结构保存了客户端当前的状态信息 客户端的套接字描述符 客户端的名字 客户端的标志值 只想客户端正在使用的数据库的指针,以及该 ...

  9. Jenkins 自定义构建结果

    1. Jenkins 构建原理 2. 脚本执行失败立即停止执行 3. 脚本执行失败继续后面的执行但最终的结果是构建失败 1. Jenkins 构建原理 Jenkins 的构建成功和脚本执行成功是两个事 ...

  10. [重要更新]微信小程序登录、用户信息相关接口调整:使用 wx.getUserProfile 取代 wx.getUserInfo

    2021年2月24日,微信官方团队发布了一个调整通知:<小程序登录.用户信息相关接口调整说明>,公告明确从4月13日起,所有发布的小程序将无法使用 wx.getUserInfo 接口(JS ...