Autofac 官网文档地址:

https://autofaccn.readthedocs.io/zh/latest/index.html

本文主要讲述如何使用 Autofac 框架完成依赖注入等操作,不涉及理论。

Autofac 的使用

我们在 .NET Core 控制台程序中进行测试和实践。

1,简单的实践

首先我们添加一个接口以及实现:

    public interface IMyService { }

    public class MyService : IMyService { }

然后在 Main 方法中注册以及构建容器:

    class Program
{
private static IContainer Container;
static void Main(string[] args)
{
// 创建容器构建器
var builder = new ContainerBuilder(); // 注册组件
builder.RegisterType<MyService>().As<IMyService>();
// ... // 构建容器
Container = builder.Build();
}
}

我们则可以这样使用:

        public static void Test()
{
// 生命周期管理
using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
// 获取实例
IMyService myService = scope.Resolve<IMyService>();
}
}

.AS() 用于暴露组件的服务。

这就是 Autofac 的简单使用。

下面我们来讨论更详细的使用方法以及实践。

2,注册组件

前面我们通过 ContainerBuilder 对象来注册组件并且告诉容器有哪些组件暴露了哪些服务。

组件的注册方式有很多种,前面我们使用了反射的方法去注册,传递一个泛型参数进去:

.RegisterType<MyService>()

或者通过类型(Type)进行注入:

            builder.RegisterType(typeof(MyService)).As<IMyService>();

当然,通过反射注册的组件,它会自动为你注入相应的构造函数。

你也可以通过 UsingConstructor 方法,要求容器实例化组件时,使用哪一个构造函数:

builder.RegisterType<MyComponent>()
.UsingConstructor(typeof(ILogger), typeof(IConfigReader));

我们也可以提前将实例注册进去:

            MyService t = new MyService();

            builder.RegisterInstance(t).As<IMyService>();

这样就会生成一个单例应用。

不过,因为 RegisterInstance(t) 会保留对 t 的引用,也就是说将这个实例注册到容器的实例中。

当然你可以使用 Lambda 表达式树来 new :

            builder.Register(c => new MyService()).As<IMyService>();

这样可以避免外部有引用。

如果你不想这样,可以使用 ExternallyOwned 方法,这样就会生成一个新的实例到容器中。如果你会 AutoMapper ,这样会很容易理解。

            builder.RegisterInstance(t).As<IMyService>().ExternallyOwned();

3,Lambda 注册组件

如果一个类型的构造函数依赖于另一个接口,那么这种类型作为组件注册,就会复杂一些,我们可以使用 Lambda 表达式来注册组件。

有以下几个接口和类型:

    public interface IA { }

    public class A : IA { }
public interface IB { } public class B : IB
{
private IA _a;
public B(IA a)
{
_a = a;
}
}

那么我们可以先注册 A 类型,再注册 B 类型:

            builder.RegisterType<A>().As<IA>();

            builder.Register(c => new B(c.Resolve<IA>()));

当然,这里使用表达式来介绍方便性。你也可以这样使用:

            builder.RegisterType<A>().As<IA>();

            builder.RegisterType<B>().As<IB>();

实例化 B 类型时,会自动为其注入构造函数。

4,注册泛型

如果要对泛型类型进行注册:

    public interface IA { }

    public class A<T> : IA { }

则可以使用 RegisterGeneric 来注册泛型组件:

            builder.RegisterGeneric(typeof(A<>)).As<IA>();

当然,如果 IA 也是泛型的话,应该使用 .As(typeof(IA))

5,属性注入

注册组件时,使用 PropertiesAutowired 方法,那么容器在生成实例时,会自动注入属性。

有以下类型:

    public interface IA { }

    public class A : IA { }
public interface IB { } public class B : IB
{
public IA A { get; set; }
}

注册:

            builder.RegisterType<A>().As<IA>();
builder.RegisterType<B>().PropertiesAutowired().As<IB>();

那么,容器会自动给 B 类型的属性注入依赖。

当然,这样会为类型的每一个属性注入依赖。

如果我们只是想为某个属性注入的话,可以这样 使用 WithProperty 方法,例如:

            builder.RegisterType<B>().WithProperty("A",new A()).As<IB>();

6,解析服务

注册组件后,调用 Build() 方法生成了容器(IContainer)。

然后使用 Resolve 方法在其生命周期内解析服务。

参考前面的示例如下:

            using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
// 获取实例
IMyService myService = scope.Resolve<IMyService>();
}

要注意的是,实例是从生命周期中解析(ILifetimeScope scope),而不是从容器中(IContainer)中解析。

如果想知道一个服务是否已经被注册,我们可以使用 ResolveOptional()TryResolve() 方法。

            using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
IB b;
// 获取实例
if (scope.TryResolve<IB>(out b))
{ }
}

在解析时,可以传递参数,这样可以控制容器生成实例时,使用能够构造函数实例化类型。

Autofac提供了多种不同的参数匹配机制:

  • NamedParameter - 通过名称匹配目标参数
  • TypedParameter - 通过类型匹配目标参数 (需要匹配具体类型)
  • ResolvedParameter - 灵活的参数匹配

示例如下:

namespace AutofacTest
{
public interface IA { } public class A : IA
{
public A(string a, string b) { Console.WriteLine($"a = {a}, b = {b}"); }
}
class Program
{
private static IContainer Container;
static void Main(string[] args)
{
// 创建容器构建器
var builder = new ContainerBuilder();
builder.RegisterType<A>().As<IA>(); // 构建容器
Container = builder.Build(); Test();
} public static void Test()
{
// 生命周期管理
using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
IA b = scope.Resolve<IA>(new NamedParameter("a", "测试"), new NamedParameter("b", "测试"));
}
}
}

或者改成:

                IA b = scope.Resolve<IA>(new TypedParameter(typeof(string), "测试"), new TypedParameter(typeof(string), "测试"));

另外,Autofac 还支持多种关系的服务解析,其种类如下:

7,生命周期

关于生命周期,你可以参考:https://autofaccn.readthedocs.io/zh/latest/lifetime/index.html

前面我们看到,要获取实例,使用了

using (ILifetimeScope scope = Container.BeginLifetimeScope())
{ }

BeginLifetimeScope 创建一个生命周期作用域,生命周期的作用域是可释放的并且可以追踪组件的释放。

你可以使用 Dispose() 或者 using{} 形式进行生命周期释放。

你也可以:

            using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
using (ILifetimeScope sc = scope.BeginLifetimeScope())
{
}
}

8,实例作用域

实例的作用域决定了对于暴露出来的同一个服务的实例如何在多个请求之间共享。组件的作用域是在注册组件是决定的,然后显式地调用 Resolve() 返回地示例,就会出现具体的行为(单例等)。

8.1 一个依赖一个实例

在 .NET 默认的依赖注入框架中,称为 'transientfactory ,对于每个请求,每次返回的都是不一样的实例。Autofac 默认就是这种模式。

你也可以使用 InstancePerDependency 显式声明:

builder.RegisterType<Worker>().InstancePerDependency();

8.2 单一实例

SingleInstance 方法可以注册组件为单一实例:

builder.RegisterType<Worker>().SingleInstance();

8.3 生命周期作用域实例

使用 InstancePerLifetimeScope可以设置组件在一个生命周期作用域内,获取到的实例都是同一个。

另外,层叠的生命周期作用域也是不同的,例如下面的示例中,结果是 True,False

            using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
IA b = scope.Resolve<IA>();
IA bb = scope.Resolve<IA>();
Console.WriteLine(b == bb);
using (ILifetimeScope sc = scope.BeginLifetimeScope())
{ IA bbb = sc.Resolve<IA>();
Console.WriteLine(b == bbb);
}
}

另外 Autofac 还有其它方法的作用域管理,请点击链接了解: https://autofaccn.readthedocs.io/zh/latest/lifetime/instance-scope.html

9,Autofac 其它需要学习的知识

Autofac 是非常厉害的框架,本文只是挑入门基础部分讲解,其它自由度高一些的复杂一些的知识点例如:

需要查看文档学习,这里不再赘述。

ASP.NET Core

ASP.NET Core 中,2.x 和 3.x 的差异比较多,这里只以 3.x 作为示例。

1,默认依赖注入

ASP.NET Core 中,默认的依赖注入,可以使用 ConfigureServices 方法,在此方法中注册即可。

例如:

        public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IA, A>();
}

2,使用 Autofac

如果要在 ASP.NET Core 中使用 Autofac 作为依赖注入容器,则还需要安装名为 Microsoft.Extensions.DependencyInjection.Abstractions 的 Nuget 包。

然后在 Program 的 Host 中加上

               .UseServiceProviderFactory(new AutofacServiceProviderFactory())

示例如下:

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

然后在 Startup 类中,加上 ConfigureContainer 方法,然后在此方法中注册需要的组件:

        public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<A>().As<IA>();
}

最后在 ConfiguraServices 方法中添加:

services.AddOptions();

即可使用 Autofac 作为 ASP.NET Core 依赖注入容器。

完整代码:

        public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddControllers();
}
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<A>().As<IA>();
}

ABP

首先要求你添加了一个 ASP.NET Core 程序,然后配置 ABP ,引入相应的包。可以参考 https://docs.abp.io/zh-Hans/abp/latest/Getting-Started-AspNetCore-Application

ABP 中,默认也是使用 ConfigureServices 直接注入即可,使用示例:

    public class AppModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient<IA, A>();
}
}

context.Services 即为 IServiceCollection 对象。

当然,ABP 也可以使用 Autofac 作为依赖注入容器。

ABP 中要使用 Autofac,需要引用 Volo.Abp.Autofac 包。

然后在模块中加上 [DependsOn(typeof(AbpAutofacModule))] 特性。

    [DependsOn(typeof(AbpAutofacModule))]
public class AppModule : AbpModule{}

然后在 Startup 中的 ConfiguraServices 方法中,添加 ABP 模块, 并且设置使用 Autofac。

        public void ConfigureServices(IServiceCollection services)
{ services.AddApplication<BasicAspNetCoreApplication.AppModule>(options=>
{
options.UseAutofac();
});
}

Autofac入门与替代ASP.NET Core、ABP依赖注入容器的更多相关文章

  1. Asp.net core自定义依赖注入容器,替换自带容器

    依赖注入 在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repos ...

  2. 几十行代码实现ASP.NET Core自动依赖注入

    在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...

  3. ASP.NET Core之依赖注入

    本文翻译自:http://www.tutorialsteacher.com/core/dependency-injection-in-aspnet-core ASP.NET Core支持依赖注入,依赖 ...

  4. 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类

    依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...

  5. asp.net core ioc 依赖注入

    1.生命周期 内置的IOC有三种生命周期: Transient: Transient服务在每次被请求时都会被创建.这种生命周期比较适用于轻量级的无状态服务. Scoped: Scoped生命周期的服务 ...

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

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

  7. ASP.NET Core:依赖注入

    ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core应用程序可以利用内置的框架服务将它们注入到启动类的方法中,并且应用程序服务能够配置注入.由ASP.NET Core提供的默 ...

  8. .net core从依赖注入容器获取对象

    创建引擎方法:该方法用于在不使用构造注入的情况下从依赖注入容器中获取对象 /// <summary> /// 一个负责创建对象的引擎 /// </summary> public ...

  9. IdentityServer4 中文文档 -14- (快速入门)使用 ASP.NET Core Identity

    IdentityServer4 中文文档 -14- (快速入门)使用 ASP.NET Core Identity 原文:http://docs.identityserver.io/en/release ...

  10. Asp.Net Core 进阶(三)—— IServiceCollection依赖注入容器和使用Autofac替换它

    Asp.Net Core 提供了默认的依赖注入容器 IServiceCollection,它是一个轻量级的依赖注入容器,所以功能不多,只是提供了基础的一些功能,要实现AOP就有点麻烦,因此在实际工作当 ...

随机推荐

  1. iframe父页面传递参数给子页面

    父页面通过ifarame传递参数 有些时候,我们需要在嵌套页面. 我们就需要使用iframe了. 通过iframe传递参数给子页面. 需求描述,当我们点击按钮的时候. 传递参数给子页面.子页面接受后展 ...

  2. echarts的初始化和销毁dispose

    容器节点被销毁以及被重建时 假设页面中存在多个标签页, 每个标签页都包含一些图表. 当选中一个标签页的时候,其他标签页的内容在 DOM 中被移除了. 这样,当用户再选中这些标签页的时候,就会发现图表& ...

  3. CANVAS ----- 鼠标移动画圆

    1.增加鼠标移动事件 $('#canvas').mousemove(function (e) { draw(event); }); 2.获取鼠标在canvas上的坐标 function getCanv ...

  4. 关于飞桨UIE等模型预测推理时间很久的问题分析以及解决,蒸馏剪枝部署问题解决

    1.关于飞桨UIE等模型预测推理时间很久的问题分析以及解决 1.1.原因分析 用uie做实体识别,Taskflow预测的时间与schema内的实体类别数量成正比,schema里面有多少个实体类别 实体 ...

  5. 推荐系统[四]:精排-详解排序算法LTR (Learning to Rank)_ poitwise, pairwise, listwise相关评价指标,超详细知识指南。

    0.前言召回排序流程策略算法简介 推荐可分为以下四个流程,分别是召回.粗排.精排以及重排: 召回是源头,在某种意义上决定着整个推荐的天花板: 粗排是初筛,一般不会上复杂模型: 精排是整个推荐环节的重中 ...

  6. Python 封装zabbix-get接口

    Zabbix 是一款强大的开源网管监控工具,该工具的客户端与服务端是分开的,我们可以直接使用自带的zabbix_get命令来实现拉取客户端上的各种数据,在本地组装参数并使用Popen开子线程执行该命令 ...

  7. Linux输出转换命令 xargs

    一.基本用法 xargs命令的作用,是将标准输入转为命令行参数. 原因:大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数 如下面 echo 不接受标准输出做参 ...

  8. electron、nodejs、typescript、idea 组合开发,安装和配置 以及错误 等 详细说明

    1.  创建项目,创建时 选择 nodejs 项目,因为 开发 electron 与 开发 nodejs 基本一致. 2.安装 electron  npm i -D electron@beta 看目录 ...

  9. 如何在windows端安装和配置maven

    1.下载maven 从官方下载maven,下载页面:http://maven.apache.org/download.cgi 2.安装maven maven压缩包解压到一个没有中文,空格或其他特殊字符 ...

  10. CF1499

    A 氵 B 如果 11 后出现了 00 就不行. C 枚举走几段. 横竖可以分开算. 一定是:除了费用最小的都是走长度 \(1\),费用最小的包揽剩下的. D \(c\cdot lcm(a,b)-d\ ...