今天就跟大家聊聊有關(guān)ASP.NET Core中如何采用Autofac來替換IOC容器并實現(xiàn)屬性注入,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
10余年的梁園網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整梁園建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“梁園網(wǎng)站設(shè)計”,“梁園網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。
今天我們主要講講如何采用Autofac來替換IOC容器,并實現(xiàn)屬性注入
首先,我們需要從nuget引用相關(guān)的包.
Autofac
Autofac.Extensions.DependencyInjection(這個包擴(kuò)展了一些微軟提供服務(wù)的類.來方便替換autofac)
然后,我們修改Startup中的ConfigureServices代碼如下:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext
services.AddDirectoryBrowser();
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule
containerBuilder.Populate(services);
var container = containerBuilder.Build();
return new AutofacServiceProvider(container);
}
這里我們使用了AutoFac的功能之一,模塊化注入.也就是RegisterModule 這里, DefaultModule是我們的注入模塊,代碼很簡單,如下:
public class DefaultModule : Module
{
protected override void Load(ContainerBuilder builder)
{
//注入測試服務(wù)
builder.RegisterType
}
}
解釋一下,在上面的代碼中,我們配置IServiceProvider從Autofac容器中解析(設(shè)置一個有效的Autofac服務(wù)適配器)。
然后在整個框架中使用它來解析控制器的依賴關(guān)系,并在HttpContext上公開所有其他用例的服務(wù)定位。
這樣我們就完成了初步的Autofac容器替換.下面我們創(chuàng)建控制器來看看效果.代碼如下:
public class AutoDIController : Controller
{
private readonly ITestService _testService;
public AutoDIController(ITestService testService)
{
_testService = testService;
}
// GET: AutoDI
public ActionResult Index()
{
ViewBag.date = _testService.GetList("Name");
return View();
}
}
當(dāng)框架(通過一個命名為DefaultControllerActivator的服務(wù))要創(chuàng)建一個控制器的實例時,它會解析IServiceProvider的所有構(gòu)造函數(shù)依賴項.在上面的代碼中,它會使用Autofac容器來解析產(chǎn)生類。
這樣就能初步的達(dá)到我們替換IOC容器的的效果了..
但是,這個操作過程與asp.net MVC的不同之處在于.控制器本身不會從容器中解析出來,所以服務(wù)只能從它的構(gòu)造器參數(shù)中解析出來。
所以.這個過程,讓我們無法使用Autofac的一些更高級功能.比如屬性注入(關(guān)于屬性注入的好壞..屬于仁者見仁智者見智的東西,這里我們不討論它是好還是壞.)
我們回到Autofac設(shè)置代碼,并設(shè)置屬性注入如下:
var containerBuilder = new ContainerBuilder();
//模塊化注入
containerBuilder.RegisterModule
//屬性注入控制器
containerBuilder.RegisterType
containerBuilder.Populate(services);
注入模塊的代碼修改如下:
//屬性注入builder.RegisterType().As ().PropertiesAutowired();
然后修改我們的控制器代碼如下:
public class AutoDIController : BaseController
{
public ITestService _testService { get; set; }
// GET: AutoDI
public ActionResult Index()
{
ViewBag.date = _testService.GetList("Name");
return View();
}
}
這里我們剔除了控制器的構(gòu)造函數(shù).
我們運行代碼,會發(fā)現(xiàn)_testService 為null,所以根本沒有注入成功.失敗的原因上面我們已經(jīng)解釋過了...但是還是強(qiáng)調(diào)一下吧..
雖然控制器的構(gòu)造函數(shù)依賴性將由MVC從IServiceProvider解決(也就是我們之前構(gòu)造函數(shù)注入的例子),
但是控制器本身的實例(以及它的處理)卻是由框架創(chuàng)建和擁有的,而不是由容器所有。
那么我們該如何改變控制器本身的創(chuàng)建和所有者呢?
我們會在Microsoft.Extensions.DependencyInjection中找到一個方法.叫做AddControllersAsServices
它的注釋翻譯過來為:將控制器的寄宿器轉(zhuǎn)為注冊的服務(wù)(也就是我們替換的autofac).
但是,注意..這里雖然是將控制的所有者改成了autofac,但是我們還是不能使用相關(guān)的屬性注入方法.
所以,我們到GITHUB上來看看這個方法源碼如下.(這就是開源的好處...):
public static IMvcBuilder AddControllersAsServices(this IMvcBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
var feature = new ControllerFeature();
builder.PartManager.PopulateFeature(feature);
foreach (var controller in feature.Controllers.Select(c => c.AsType()))
{
builder.Services.TryAddTransient(controller, controller);
}
builder.Services.Replace(ServiceDescriptor.Transient
return builder;
}
我們會發(fā)現(xiàn)最后一句..
builder.Services.Replace(ServiceDescriptor.Transient());
意思是用ServiceBasedControllerActivator替換DefaultControllerActivator(意味著框架現(xiàn)在會嘗試從IServiceProvider中解析控制器實例)
..這下終于真相大白了..
我們只需要修改配置服務(wù)的代碼如下:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//替換控制器所有者
services.Replace(ServiceDescriptor.Transient
services.AddMvc();
services.AddDbContext
services.AddDirectoryBrowser();
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule
//采用屬性注入控制器
containerBuilder.RegisterType
// containerBuilder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired();
containerBuilder.Populate(services);
var container = containerBuilder.Build();
return new AutofacServiceProvider(container);
}
注意,替換的方法一定要在addMVC之前..
然后我們運行我們的控制器代碼.效果如圖:
如圖所示,_testService已經(jīng)被實例化了.說明我們的屬性注入就成功了~
看完上述內(nèi)容,你們對ASP.NET Core中如何采用Autofac來替換IOC容器并實現(xiàn)屬性注入有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。