autofac 作用域_C#编程之.Net Core 学习之路-AutoFac的使用
本文主要向大家介紹了C#編程之.Net Core 學習之路-AutoFac的使用,通過具體的內(nèi)容向大家展示,希望對大家學習C#編程有所幫助。
本文不介紹IoC和DI的概念,如果你對Ioc之前沒有了解的話,建議先去搜索一下相關(guān)的資料
這篇文章將簡單介紹一下AutoFac的基本使用以及在asp .net core中的應用
Autofac介紹
組件的三種注冊方式反射
現(xiàn)成的實例(new)
lambda表達式 (一個執(zhí)行實例化對象的匿名方法)
下面是一些簡短的示例,我盡可能多的列出來一些常用的注冊方式,同時在注釋中解釋下“組件”、“服務”等一些名詞的含義//?創(chuàng)建注冊組件的buildervar?builder?=?new?ContainerBuilder();//根據(jù)類型注冊組件?ConsoleLogger?暴漏服務:ILoggerbuilder.RegisterType().As();//根據(jù)類型注冊組件?ConsoleLogger,暴漏其實現(xiàn)的所有服務(接口)builder.RegisterType().AsImplementedInterfaces();//?根據(jù)實例注冊組件?output??暴漏服務:TextWritervar?output?=?new?StringWriter();
builder.RegisterInstance(output).As();//表達式注冊組件,這里我們是在構(gòu)造函數(shù)時傳參->"musection"???暴漏服務:IConfigReaderbuilder.Register(c?=new?ConfigReader("mysection")).As();//表達式注冊組件,解析時傳參var?service?=?scope.Resolve(???????????new?NamedParameter("section",?"mysection"));
//反射注冊組件,直接注冊了ConsoleLogger類(必須是具體的類),如果ConsoleLogger有多個構(gòu)造函數(shù),將會取參數(shù)最多的那個構(gòu)造函數(shù)進行實例化builder.RegisterType();//反射注冊組件,手動指定構(gòu)造函數(shù),這里指定了調(diào)用?MyComponent(ILogger?log,IConfigReader?config)的構(gòu)造函數(shù)進行注冊builder.RegisterType()
.UsingConstructor(typeof(ILogger),?typeof(IConfigReader));
//注冊MySingleton類中的靜態(tài)變量"Instance",ExternallyOwned()函數(shù)指定自己控制實例的生命周期,而不是由autofac自動釋放
builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();//一個組件暴漏兩個服務??builder.RegisterType().As().As();
//注冊當前程序集中以“Service”結(jié)尾的類builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t?=>?t.Name.EndsWith("Service")).AsImplementedInterfaces();//注冊"MyApp.Repository"程序集中所有的類builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
//構(gòu)建一個容器完成注冊var?rootcontainer?=?builder.Build();//可以通過下面這種方式手動獲取IConfigReader?的實現(xiàn)類//這種手動解析的方式需要?從生命周期作用域內(nèi)獲取組件,以保證組件最終被釋放//不要直接從根容器rootcontainer中解析組件,很有可能會導致內(nèi)存泄漏using(var?scope?=?rootcontainer.BeginLifetimeScope())
{??var?reader?=?scope.Resolve();
}
如果不止一個組件暴露了相同的服務, Autofac將使用最后注冊的組件作為服務的提供方。 想要覆蓋這種行為, 在注冊代碼后使用?PreserveExistingDefaults()?方法修改
生命周期using(var scope = rootcontainer.BeginLifetimeScope())
上面的這段代碼創(chuàng)建了一個生命周期作用域
生命周期作用域是可釋放的,在作用域內(nèi)解析的組件一定要保證在using之內(nèi)使用或者最后手動調(diào)用組件的Dispose()函數(shù)
避免被引用類的生命周期大于引用類的生命周期 :如service 引用 repository 如果repository的生命周期為單例,service的生命周期為perrequest。repository不會釋放,所以最終會造成相關(guān)的service始終無法釋放的情況(Captive Dependencies)
對于一個具體組件(類)的生命周期分為以下幾種(后面的函數(shù)是autofac對應的函數(shù)):每個依賴一個實例(Instance Per Dependency) (默認) ----InstancePerDependency()
單一實例(Single Instance)?單例?----SingleInstance()
每個生命周期作用域一個實例(Instance Per Lifetime Scope)----InstancePerLifetimeScope()
每個匹配的生命周期作用域一個實例(Instance Per Matching Lifetime Scope)----InstancePerMatchingLifetimeScope()
每個請求一個實例(Instance Per Request)?asp.net web請求----InstancePerRequest()
每次被擁有一個實例(Instance Per Owned) ----InstancePerOwned()
如果你以前在傳統(tǒng)的ASP.NET MVC項目中用過autofac,需要注意一些區(qū)別:.net Core中需要使用InstancePerLifetimeScope替代之前(傳統(tǒng)asp.net)的InstancePerRequest,保證每次HTTP請求只有唯一的依賴實例被創(chuàng)建。InstancePerRequest請求級別已經(jīng)不存在了
.net Core中Web Api與Mvc的注冊方式一樣
.net Core中不再需要注冊控制器,控制器由.net core創(chuàng)建,不歸autofac管理(除了控制器的構(gòu)造函數(shù)),這也解釋了為什么不再使用InstancePerRequest生命周期,但是可以通過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還是比較簡單的,相比于傳統(tǒng)的asp.net web 項目,省去了很多步驟
引入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)
{????????//注冊服務進?IServiceCollection
services.AddMvc();
ContainerBuilder?builder?=?new?ContainerBuilder();????????//將services中的服務填充到Autofac中.
builder.Populate(services);????????//新模塊組件注冊
builder.RegisterModule();????????//創(chuàng)建容器.
AutofacContainer?=?builder.Build();????????//使用容器創(chuàng)建?AutofacServiceProvider
return?new?AutofacServiceProvider(AutofacContainer);
}上面代碼調(diào)用了builder的RegisterModule函數(shù),這個函數(shù)需要傳入一個TModule的泛型,稱之為autofac的模塊
模塊的功能就是把所有相關(guān)的注冊配置都放在一個類中,使代碼更易于維護和配置,下面展示了DefaultModuleRegister中的代碼
DefaultModuleRegister:public?class?DefaultModuleRegister?:?Module{????protected?override?void?Load(ContainerBuilder?builder)????{????????//注冊當前程序集中以“Ser”結(jié)尾的類,暴漏類實現(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();????????//注冊所有"MyApp.Repository"程序集中的類
//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ù)中可以選擇性的加上程序停止時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();????????????IHostingEnvironment?env?=?scope.Resolve();
}????????string?name?=?_user.GetName();????????string?name2?=?_user2.GetName();????????return?View();
}可以看到,因為我們將IServiceCollection中的服務填充到了autofac中了,所以現(xiàn)在可以在任何位置通過AutoFac解析出來.net core默認注入的服務(IConfiguration,IHostingEnvironment等)了
正常項目使用中,我們應該將AutofacContainer放在一個公共的類庫中以便各個工程均可調(diào)用
本文由職坐標整理并發(fā)布,希望對同學們有所幫助。了解更多詳情請關(guān)注職坐標編程語言C#.NET頻道!
總結(jié)
以上是生活随笔為你收集整理的autofac 作用域_C#编程之.Net Core 学习之路-AutoFac的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 写给那些傻傻的,想做服务器开发的应届生
- 下一篇: ubuntu搭建一个简单的http服务器