autofac 作用域_.Net Core3.1下使用Autofac实现依赖注入
前言
Autofac是.NET領(lǐng)域最為流行的IOC框架之一,傳說是速度最快的一個。它和C#語言的結(jié)合非常緊密,在使用過程中對你的應用的侵入性幾乎為零,更容易與第三方的組件集成。主要優(yōu)點如下(此段描述為轉(zhuǎn)載):它是C#語言聯(lián)系很緊密,也就是說C#里的很多編程方式都可以為Autofac使用,例如可以用Lambda表達式注冊組件
較低的學習曲線,學習它非常的簡單,只要你理解了IoC和DI的概念以及在何時需要使用它們
XML配置支持
自動裝配
微軟的Orchad開源程序使用的就是Autofac,從該源碼可以看出它的方便和強大
準備工作
本文演示的項目時基于.Net Core3.1的,同時需要通過nuget下載安裝以下幾個dll文件:
基本用法
在前面的《基于Dapper的擴展方法來簡單封裝WebApi接口》一文中介紹過在.net core2.1中使用Autofac的方式,在ASP.NET Core 1.1 - 2.2 中, 你可以調(diào)用 WebHostBuilder 的 services.AddAutofac().。但這不適用于ASP.NET Core 3+ 或 .NET Core 3+ ,在 ASP.NET Core 3+ 需要你直接指定一個service provider factory而不是把它加入進service collection。基本用法的代碼如下:
首先修改Progam中的CreateHostBuilder方法,使用autofac的容器工廠替換系統(tǒng)默認的容器:public?static?IHostBuilder?CreateHostBuilder(string[]?args)?=>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new?AutofacServiceProviderFactory())//使用autofac的容器工廠替換系統(tǒng)默認的容器
.ConfigureWebHostDefaults(webBuilder?=>
{
webBuilder.UseStartup();
});
然后在Startup中增加一個方法ConfigureContainerpublic?void?ConfigureContainer(ContainerBuilder?containerBuilder)
{
//指定服務的注冊
containerBuilder.RegisterType().As().InstancePerLifetimeScope().AsImplementedInterfaces();
containerBuilder.RegisterType().As().InstancePerLifetimeScope().AsImplementedInterfaces();
var?container?=?containerBuilder.Build();
IUserService?userService?=?container.Resolve();
IProductService?productService?=?container.Resolve();
userService.Show();
productService.Show();
}
調(diào)試運行,我們發(fā)現(xiàn)ConfigureContainer的方法并沒有被引用,但已經(jīng)可以進到這個方法里并實現(xiàn)的服務的注冊,這就是因為我們指定了UseServiceProviderFactory:
Autofac生命周期
簡單介紹,詳情請見參考資料://1、瞬時生命周期:注冊之后,每次獲取到的服務實例都不一樣(默認的注冊方式)
containerBuilder.RegisterType().As().InstancePerDependency();
//2、單例生命周期:整個容器中獲取的服務實例都是同一個
containerBuilder.RegisterType().As().SingleInstance();
//3、作用域生命周期:在相同作用域下獲取到的服務實例是相同的
containerBuilder.RegisterType().As().InstancePerLifetimeScope();
//4、作用域生命周期:可以指定到某一個作用域,然后在相同作用域下共享服務實例
containerBuilder.RegisterType().As().InstancePerMatchingLifetimeScope("My");
//5、http請求上下文的生命周期:在一次Http請求上下文中,共享一個組件實例。僅適用于asp.net?mvc開發(fā)。
containerBuilder.RegisterType().As().InstancePerRequest();
//6、擁有隱式關(guān)系類型的創(chuàng)建新的嵌套生命周期的作用域,在一個生命周期域中所擁有的實例創(chuàng)建的生命周期中,
//??????每一個依賴組件或調(diào)用Resolve()方法創(chuàng)建一個單一的共享的實例,并且子生命周期域共享父生命周期域中的實例
containerBuilder.RegisterType().InstancePerOwned();
實際項目中用法
上面的代碼只是簡單演示了下Autofac如何注冊服務實例的,在實際使用時我們不會這樣去寫代碼,每增加一個接口及其實現(xiàn),都需要手動注冊一下,這樣的耦合度太高。因此我們需要進行代碼優(yōu)化,下面將使用反射的方式來實現(xiàn)服務的注冊,改造上面的代碼:public?void?ConfigureContainer(ContainerBuilder?containerBuilder)
{
Assembly?service?=?Assembly.Load("AspNetCore.Ioc.Service");
Assembly?iservice?=?Assembly.Load("AspNetCore.Ioc.Interface");
containerBuilder.RegisterAssemblyTypes(service,?iservice)
.Where(t?=>?t.FullName.EndsWith("Service")?&&?!t.IsAbstract)?//類名以service結(jié)尾,且類型不能是抽象的
.InstancePerLifetimeScope()?//生命周期,,
.AsImplementedInterfaces()
.PropertiesAutowired();?//屬性注入
}
運行結(jié)果如下
一個接口多個實現(xiàn)的服務注冊
在實際應用中有這樣一種場景,比如IUserService接口被多個類繼承并實現(xiàn),那么此時應該如何注冊服務并實現(xiàn)調(diào)用呢?
其實上面Startup中的注冊方式就已經(jīng)滿足服務的注冊,只是需要在相應的Controller調(diào)用的地方修改即可,如:public?class?UserController?:?Controller
{
///?
///?IUserService服務實現(xiàn)的集合
///?
private?readonly?IEnumerable?_userServices?=?null;
public?UserController(IEnumerable?userServices)
{
_userServices?=?userServices;
}
public?IActionResult?Index()
{
foreach?(var?item?in?_userServices)
{
item.Show();
}
return?View();
}
}
調(diào)試運行的結(jié)果如下
值得說明的是,一個接口有多個實現(xiàn)的情況,在注冊服務的時候,可以選擇一些策略來實現(xiàn)只注冊其中某幾個實例,示例代碼如下://一個接口有多個實現(xiàn):注冊所有實現(xiàn)的服務實例
builder.RegisterAssemblyTypes(Assembly.Load("AspNetCore.Ioc.Service")).As();
//一個接口有多個實現(xiàn):只注冊以A結(jié)尾的服務實例
builder.RegisterAssemblyTypes(Assembly.Load("AspNetCore.Ioc.Service")).Where(c=>c.Name.EndsWith("A")).As();
//一個接口有多個實現(xiàn):注冊所有實現(xiàn)的服務實例,并排除UserServiceA服務實例
builder.RegisterAssemblyTypes(Assembly.Load("AspNetCore.Ioc.Service")).Except().As();
隔離服務注冊的邏輯代碼
為了簡化Startup中的代碼,還可以自定義一個MyAutofacModule的方式,將服務注冊的代碼抽離出來,放到單獨的文件中。這時我們就需要新建一個MyAutofacModule類,并繼承Autofac.Module,同時重寫其中的Load方法,具體代碼如下:using?System.Linq;
using?System.Reflection;
using?Autofac;
using?Autofac.Configuration;
using?Microsoft.Extensions.Configuration;
namespace?AspNetCore.Ioc.Web.Utility
{
public?class?MyAutofacModule?:?Autofac.Module
{
protected?override?void?Load(ContainerBuilder?builder)
{
//反射程序集方式服務注冊
Assembly?service?=?Assembly.Load("AspNetCore.Ioc.Service");
Assembly?iservice?=?Assembly.Load("AspNetCore.Ioc.Interface");
builder.RegisterAssemblyTypes(service,?iservice)
.Where(t?=>?t.FullName.EndsWith("Service")?&&?!t.IsAbstract)?//類名以service結(jié)尾,且類型不能是抽象的
.InstancePerLifetimeScope()?//作用域生命周期
.AsImplementedInterfaces()
.PropertiesAutowired();?//屬性注入
}
}
}
重寫Load方法中的邏輯其實就是將原本 寫在Startup中的注冊代碼遷移到MyAutofacModule中,然后將Startup中的ConfigureContainer方法修改成如下:public?void?ConfigureContainer(ContainerBuilder?containerBuilder)
{
containerBuilder.RegisterModule();
}
具體運行結(jié)果這里就不展示,和前面的一樣。
配置文件的方式服務注冊
為了讓注冊服務的方式更靈活,我們還可以通過配置文件的方式來實現(xiàn),將所有的程序集信息放到配置文件中,這樣便于后期的程序擴展。那么首先來看下配置文件應該如何寫:
需要注意的是要將autofac.json文件的屬性改成始終復制
autofac.json文件:{
"defaultAssembly":?"AspNetCore.Ioc.Interface",?//接口所在的程序集名稱
"components":?[
{
"type":?"AspNetCore.Ioc.Service.UserService,AspNetCore.Ioc.Service",?//接口的實現(xiàn)?全名稱
"services":?[
{
"type":?"AspNetCore.Ioc.Interface.IUserService"?//?接口的全名稱
}
],
"instanceScope":?"single-instance",?//單例生命周期
"injectProperties":?true?//是否支持屬性注入
},
{
"type":?"AspNetCore.Ioc.Service.ProductService,AspNetCore.Ioc.Service",?//接口的實現(xiàn)?全名稱
"services":?[
{
"type":?"AspNetCore.Ioc.Interface.IProductService"?//?接口的全名稱
}
],
"instanceScope":?"single-instance",?//單例生命周期
"injectProperties":?true?//是否支持屬性注入
}
]
}
修改MyAutofacModule中的調(diào)用方法:protected?override?void?Load(ContainerBuilder?builder)
{
//Autofac?基于配置文件的服務注冊
IConfigurationBuilder?configurationBuilder?=?new?ConfigurationBuilder();
configurationBuilder.AddJsonFile("Config/autofac.json");
IConfigurationRoot?root?=?configurationBuilder.Build();
//開始讀取配置文件中的內(nèi)容
ConfigurationModule?module?=?new?ConfigurationModule(root);
//根據(jù)配置文件的內(nèi)容注冊服務
builder.RegisterModule(module);
}
運行結(jié)果如下
總結(jié)
到這里基本就完成了.net core3.1下使用Autofac的基本用法,當然還有其他的一些用法,比如Autofac中實現(xiàn)AOP等,本文暫時就到這里了。參考資料:
總結(jié)
以上是生活随笔為你收集整理的autofac 作用域_.Net Core3.1下使用Autofac实现依赖注入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EXCEL散点图改横轴坐标
- 下一篇: .Net Core3.1下Autofac