.Net Core 之AutoFac的使用
本文不介紹IoC和DI的概念,如果你對(duì)Ioc之前沒(méi)有了解的話(huà),建議先去搜索一下相關(guān)的資料
這篇文章將簡(jiǎn)單介紹一下AutoFac的基本使用以及在asp .net core中的應(yīng)用
Autofac介紹
組件的三種注冊(cè)方式
1.反射
2.現(xiàn)成的實(shí)例(new)
3.lambda表達(dá)式 (一個(gè)執(zhí)行實(shí)例化對(duì)象的匿名方法)
下面是一些簡(jiǎn)短的示例,我盡可能多的列出來(lái)一些常用的注冊(cè)方式,同時(shí)在注釋中解釋下“組件”、“服務(wù)”等一些名詞的含義
// 創(chuàng)建注冊(cè)組件的builder
var builder = new ContainerBuilder();
//根據(jù)類(lèi)型注冊(cè)組件 ConsoleLogger 暴漏服務(wù):ILogger
builder.RegisterType<ConsoleLogger>().As<ILogger>();
//根據(jù)類(lèi)型注冊(cè)組件 ConsoleLogger,暴漏其實(shí)現(xiàn)的所有服務(wù)(接口)
builder.RegisterType<ConsoleLogger>().AsImplementedInterfaces();
// 根據(jù)實(shí)例注冊(cè)組件 output 暴漏服務(wù):TextWriter
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
//表達(dá)式注冊(cè)組件,這里我們是在構(gòu)造函數(shù)時(shí)傳參->"musection" 暴漏服務(wù):IConfigReader
builder.Register(c =new ConfigReader("mysection")).As<IConfigReader>();
//表達(dá)式注冊(cè)組件,解析時(shí)傳參
var service = scope.Resolve<IConfigReader>(
new NamedParameter("section", "mysection"));
//反射注冊(cè)組件,直接注冊(cè)了ConsoleLogger類(lèi)(必須是具體的類(lèi)),如果ConsoleLogger有多個(gè)構(gòu)造函數(shù),將會(huì)取參數(shù)最多的那個(gè)構(gòu)造函數(shù)進(jìn)行實(shí)例化
builder.RegisterType<ConsoleLogger>();
//反射注冊(cè)組件,手動(dòng)指定構(gòu)造函數(shù),這里指定了調(diào)用 MyComponent(ILogger log,IConfigReader config)的構(gòu)造函數(shù)進(jìn)行注冊(cè)
builder.RegisterType<MyComponent>()
.UsingConstructor(typeof(ILogger), typeof(IConfigReader));
//注冊(cè)MySingleton類(lèi)中的靜態(tài)變量"Instance",ExternallyOwned()函數(shù)指定自己控制實(shí)例的生命周期,而不是由autofac自動(dòng)釋放
builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();
//一個(gè)組件暴漏兩個(gè)服務(wù)
builder.RegisterType<CallLogger>().As<ILogger>().As<ICallInterceptor>();
//注冊(cè)當(dāng)前程序集中以“Service”結(jié)尾的類(lèi)
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces();
//注冊(cè)"MyApp.Repository"程序集中所有的類(lèi)
builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
//構(gòu)建一個(gè)容器完成注冊(cè)
var rootcontainer = builder.Build();
//可以通過(guò)下面這種方式手動(dòng)獲取IConfigReader 的實(shí)現(xiàn)類(lèi)
//這種手動(dòng)解析的方式需要 從生命周期作用域內(nèi)獲取組件,以保證組件最終被釋放
//不要直接從根容器rootcontainer中解析組件,很有可能會(huì)導(dǎo)致內(nèi)存泄漏
using(var scope = rootcontainer.BeginLifetimeScope())
{
var reader = scope.Resolve<IConfigReader>();
}
如果不止一個(gè)組件暴露了相同的服務(wù), Autofac將使用最后注冊(cè)的組件作為服務(wù)的提供方。 想要覆蓋這種行為, 在注冊(cè)代碼后使用 PreserveExistingDefaults() 方法修改
生命周期
using(var scope = rootcontainer.BeginLifetimeScope())上面的這段代碼創(chuàng)建了一個(gè)生命周期作用域
生命周期作用域是可釋放的,在作用域內(nèi)解析的組件一定要保證在using之內(nèi)使用或者最后手動(dòng)調(diào)用組件的Dispose()函數(shù)
避免引用類(lèi)的生命周期大于被引用類(lèi)的生命周期 :如service 引用 repository 如果service的生命周期為單例,repository的生命周期為perrequest。service不會(huì)釋放,所以最終會(huì)造成相關(guān)的repository始終無(wú)法釋放的情況(Captive Dependencies)
雖然我們需要盡可能的避免直接從根容器解析組件,但總有例外的情況,對(duì)于非單例的組件,一定不要忘記調(diào)用組件的Dispose函數(shù),實(shí)際上對(duì)于非單例的組件,從項(xiàng)目架構(gòu)上來(lái)說(shuō),理論上應(yīng)該是從構(gòu)造函數(shù)注入進(jìn)去的而不是手動(dòng)解析。 需要手動(dòng)解析的應(yīng)該為一些配置幫助類(lèi)等
對(duì)于一個(gè)具體組件(類(lèi))的生命周期分為以下幾種(后面的函數(shù)是autofac對(duì)應(yīng)的函數(shù)):
- 每個(gè)依賴(lài)一個(gè)實(shí)例(Instance Per Dependency) (默認(rèn)) ----InstancePerDependency()
- 單一實(shí)例(Single Instance) 單例 ----SingleInstance()
- 每個(gè)生命周期作用域一個(gè)實(shí)例(Instance Per Lifetime Scope)----InstancePerLifetimeScope()
- 每個(gè)匹配的生命周期作用域一個(gè)實(shí)例(Instance Per Matching Lifetime Scope)----InstancePerMatchingLifetimeScope()
- 每個(gè)請(qǐng)求一個(gè)實(shí)例(Instance Per Request) asp.net web請(qǐng)求----InstancePerRequest()
- 每次被擁有一個(gè)實(shí)例(Instance Per Owned) ----InstancePerOwned()
如果你以前在傳統(tǒng)的ASP.NET MVC項(xiàng)目中用過(guò)autofac,需要注意一些區(qū)別:
- .net Core中需要使用
InstancePerLifetimeScope替代之前(傳統(tǒng)asp.net)的InstancePerRequest,保證每次HTTP請(qǐng)求只有唯一的依賴(lài)實(shí)例被創(chuàng)建。InstancePerRequest請(qǐng)求級(jí)別已經(jīng)不存在了- .net Core中Web Api與Mvc的注冊(cè)方式一樣
- .net Core中不再需要注冊(cè)控制器,控制器由.net core創(chuàng)建,不歸autofac管理(除了控制器的構(gòu)造函數(shù)),這也解釋了為什么不再使用
InstancePerRequest生命周期,但是可以通過(guò)AddControllersAsServices()函數(shù)改變,想要深入了解的可以查看:https://www.strathweb.com/2016/03/the-subtle-perils-of-controller-dependency-injection-in-asp-net-core-mvc/
AutoFac 在asp .net core中的使用
在.net core 中使用autofac還是比較簡(jiǎn)單的,相比于傳統(tǒng)的asp.net web 項(xiàng)目,省去了很多步驟
引入nuget程序包:
- Autofac
- Autofac.Extensions.DependencyInjection
startup 中代碼:
public static IContainer AutofacContainer;
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//注冊(cè)服務(wù)進(jìn) IServiceCollection
services.AddMvc();
ContainerBuilder builder = new ContainerBuilder();
//將services中的服務(wù)填充到Autofac中.
builder.Populate(services);
//新模塊組件注冊(cè)
builder.RegisterModule<DefaultModuleRegister>();
//創(chuàng)建容器.
AutofacContainer = builder.Build();
//使用容器創(chuàng)建 AutofacServiceProvider
return new AutofacServiceProvider(AutofacContainer);
}
上面代碼調(diào)用了builder的
RegisterModule函數(shù),這個(gè)函數(shù)需要傳入一個(gè)TModule的泛型,稱(chēng)之為autofac的模塊模塊的功能就是把所有相關(guān)的注冊(cè)配置都放在一個(gè)類(lèi)中,使代碼更易于維護(hù)和配置,下面展示了
DefaultModuleRegister中的代碼
DefaultModuleRegister:
public class DefaultModuleRegister : Module
{
protected override void Load(ContainerBuilder builder)
{
//注冊(cè)當(dāng)前程序集中以“Ser”結(jié)尾的類(lèi),暴漏類(lèi)實(shí)現(xiàn)的所有接口,生命周期為PerLifetimeScope
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Ser")).AsImplementedInterfaces().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces().InstancePerLifetimeScope();
//注冊(cè)所有"MyApp.Repository"程序集中的類(lèi)
//builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
}
public static Assembly GetAssembly(string assemblyName)
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(AppContext.BaseDirectory + $"{assemblyName}.dll");
return assembly;
}
}
Configure函數(shù)中可以選擇性的加上程序停止時(shí)Autofac的釋放函數(shù):
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
//程序停止調(diào)用函數(shù)
appLifetime.ApplicationStopped.Register(() => { AutofacContainer.Dispose(); });
}
Controller中代碼:
private IUserSer _user;
private IUserSer _user2;
public HomeController(IUserSer user, IUserSer user2)
{
_user = user;
_user2 = user2;
}
public IActionResult Index()
{
using (var scope = Startup.AutofacContainer.BeginLifetimeScope())
{
IConfiguration config = scope.Resolve<IConfiguration>();
IHostingEnvironment env = scope.Resolve<IHostingEnvironment>();
}
string name = _user.GetName();
string name2 = _user2.GetName();
return View();
}
可以看到,因?yàn)槲覀儗ServiceCollection中的服務(wù)填充到了autofac中了,所以現(xiàn)在可以在任何位置通過(guò)AutoFac解析出來(lái).net core默認(rèn)注入的服務(wù)(IConfiguration,IHostingEnvironment等)了
正常項(xiàng)目使用中,我們應(yīng)該將
AutofacContainer放在一個(gè)公共的類(lèi)庫(kù)中以便各個(gè)工程均可調(diào)用
到此這篇關(guān)于.Net Core 之AutoFac的使用的文章就介紹到這了,更多相關(guān).Net Core AutoFac內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在 ASP.NET Core 中自動(dòng)啟用 CAP 事務(wù)詳情
本篇文章旨在描述如何在 ASP.NET Core項(xiàng)目中并以一種簡(jiǎn)便的方式啟用CAP事務(wù),因?yàn)樵谖覀兊氖纠卸际侵苯友菔颈容^直觀的方式,沒(méi)有進(jìn)行封裝,有些初學(xué)者同學(xué)不太會(huì),找到問(wèn)我如何封裝,本篇文章主要基于 Entity Framework 來(lái)進(jìn)行演示2021-10-10
ABP入門(mén)系列應(yīng)用BootstrapTable表格插件
Bootstrap table是一個(gè)開(kāi)源的輕量級(jí)功能非常豐富的前端表格插件。下面通過(guò)本文給大家介紹ABP入門(mén)系列應(yīng)用BootstrapTable表格插件,感興趣的朋友一起學(xué)習(xí)吧2017-03-03
.net中線程同步的典型場(chǎng)景和問(wèn)題剖析
在使用多線程進(jìn)行編程時(shí),有一些經(jīng)典的線程同步問(wèn)題,對(duì)于這些問(wèn)題,.net提供了多種不同的類(lèi)來(lái)解決2012-11-11
從零開(kāi)始學(xué)ASP.NET-基礎(chǔ)篇
從零開(kāi)始學(xué)ASP.NET-基礎(chǔ)篇...2006-07-07
ASP.NET通過(guò)Web.config實(shí)現(xiàn)驗(yàn)證賬號(hào)密碼是否正確進(jìn)行登錄
本文是通過(guò)authentication(認(rèn)證訪問(wèn)者) 和 authorization( 訪問(wèn)權(quán)限),來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的判斷用戶(hù)賬號(hào)密碼是否正確,需要的朋友可以參考下2021-09-09
深入分析XmlSerializer對(duì)象的Xml序列化與反序列化的示例詳解
本篇文章是對(duì)XmlSerializer 對(duì)象的Xml序列化與反序列化的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#中string與byte[]的轉(zhuǎn)換幫助類(lèi)-.NET教程,C#語(yǔ)言
在寫(xiě)c#程序時(shí),string和byte[]之間的轉(zhuǎn)換比較煩,在移植一些老程序時(shí)感覺(jué)很不好。我在c#中使用des和tripledes時(shí)移植一塊老代碼時(shí)也遇到了同樣的情況。為了下次不為同樣的事情煩惱,就寫(xiě)了下面的幫助類(lèi)。2008-03-03
詳解如何使用Net將HTML簡(jiǎn)歷導(dǎo)出為PDF格式
這篇文章主要為大家介紹了詳解如何使用Net將HTML簡(jiǎn)歷導(dǎo)出為PDF格式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03

