本文将通过演示一个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. golang 实现最小二乘法拟合直线

    func LeastSquares(x[]float64,y[]float64)(a float64,b float64){ // x是横坐标数据,y是纵坐标数据 // a是斜率,b是截距 xi := ...

  2. (二)SpringBoot启动过程的分析-环境信息准备

    -- 以下内容均基于2.1.8.RELEASE版本 由上一篇SpringBoot基本启动过程的分析可以发现在run方法内部启动SpringBoot应用时采用多个步骤来实现,本文记录启动的第二个环节:环 ...

  3. Linux系统浮动IP的配置

    什么是浮动IP,为什么要配置浮动IP 首先说一下为什么要配置浮动IP. 原文链接:https://blog.csdn.net/readiay/article/details/53538085 现在有一 ...

  4. Hashtable 渐渐被人们遗忘了,只有面试官还记得,感动

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...

  5. exec 跟 source 差在哪?-- Shell十三问<第六问>

    exec 跟 source 差在哪?-- Shell十三问<第六问> 这次先让我们从 CU Shell 版的一个实例贴子来谈起吧: 例中的提问是: cd /etc/aa/bb/cc 可以执 ...

  6. Qt信号槽源码剖析(一)

    大家好,我是IT文艺男,来自一线大厂的一线程序员 大家在使用Qt开发程序时,都知道怎么使用Qt的信号槽,但是Qt信号槽是怎么工作的? 大部分人仍然不知道:也就是说大家只知道怎么使用,却不知道基于什么原 ...

  7. 2020 OO 第四单元总结 UML

    title: 2020 OO 第四单元总结 date: 2020-06-14 19:10:06 tags: OO categories: 学习 1. 本单元三次作业的架构设计 本单元的代码编写与第三单 ...

  8. LeetCode剑指Offer刷题总结(一)

    LeetCode过程中值得反思的细节 以下题号均指LeetCode剑指offer题库中的题号 本文章将每周定期更新,当内容达到10题左右时将会开下一节. 二维数组越界问题04 public stati ...

  9. 自动化kolla-ansible部署ubuntu20.04+openstack-victoria之实例类型-10

    自动化kolla-ansible部署ubuntu20.04+openstack-victoria之实例类型-10 欢迎加QQ群:1026880196 进行交流学习 实例类型 #controller1 ...

  10. 阿里巴巴面试-Java后端-社招5面技术总结(Offer已拿)

    最近接到阿里妈妈的面试通知,历经一个月,虽然过程挺坎坷,但总算是拿到了offer.这里简单记录下面试所遇问题,仅供各位大佬参考. 由于前面两面的时间过去的有点久了,只能根据记忆大概写些记得问题. 部门 ...