標籤: 依賴注入 Autofac ASPNETCorehtml
關於IoC模式(控制反轉)和DI技術(依賴注入),咱們已經見過不少的探討,這裏就再也不贅述了。好比說必看的Martin Fowler《IoC 容器和 Dependency Injection 模式》,相關資料連接都附於文章末尾。其中我很是贊同Artech的說法"控制更多地體現爲一種流程的控制",而依賴注入技術讓咱們的應用程序實現了鬆散耦合。git
ASP.NET Core自己已經集成了一個輕量級的IOC容器,開發者只須要定義好接口後,在Startup.cs的ConfigureServices方法裏使用對應生命週期的綁定方法便可,常見方法以下github
services.AddTransient<IApplicationService,ApplicationService> services.AddScoped<IApplicationService,ApplicationService> services.AddSingleton<IApplicationService,ApplicationService>
對於上述的三種DI注入方式,官方也給出了詳細的解釋,我來簡單翻譯一下json
在這以後,咱們即可以將服務經過構造函數注入或者是屬性注入的方式注入到Controller,View(經過使用@inject
),甚至是Filter中(之前使用Unity將依賴注入到Filter真是一種痛苦)。話很少說,先來體驗一把設計模式
Tips:Startup.cs是什麼,詳見ASP.NET Core 介紹和項目解讀瀏覽器
大多項目舉例依賴注入的生命週期演示時,都會採起可變Guid來做爲返回顯示,這次示例也會這樣處理。咱們先定義一個IGuidAppService接口,裏面定義基接口和三種注入模式的接口框架
public interface IGuidAppService { Guid GuidItem(); } public interface IGuidTransientAppService : IGuidAppService { } public interface IGuidScopedAppService : IGuidAppService { } public interface IGuidSingletonAppService : IGuidAppService { }
一樣的,在GuidAppService中定義其實現類。這裏爲了直觀顯示每次請求的返回值,採起以下代碼asp.net
public class GuidAppServiceBase : IGuidAppService { private readonly Guid _item; public GuidAppServiceBase() { _item = Guid.NewGuid(); } public Guid GuidItem() { return _item; } } public class GuidTransientAppService : GuidAppServiceBase, IGuidTransientAppService { } public class GuidScopedAppService : GuidAppServiceBase, IGuidScopedAppService { } public class GuidSingletonAppService : GuidAppServiceBase, IGuidSingletonAppService { }
最後是Controller和View視圖的代碼ide
# Controller public class HomeController : Controller { private readonly IGuidTransientAppService _guidTransientAppService; //#構造函數注入 //private IGuidTransientAppService _guidTransientAppService { get; } #屬性注入 private readonly IGuidScopedAppService _guidScopedAppService; private readonly IGuidSingletonAppService _guidSingletonAppService; public HomeController(IGuidTransientAppService guidTransientAppService, IGuidScopedAppService guidScopedAppService, IGuidSingletonAppService guidSingletonAppService) { _guidTransientAppService = guidTransientAppService; _guidScopedAppService = guidScopedAppService; _guidSingletonAppService = guidSingletonAppService; } public IActionResult Index() { ViewBag.TransientItem = _guidTransientAppService.GuidItem(); ViewBag.ScopedItem = _guidScopedAppService.GuidItem(); ViewBag.SingletonItem = _guidSingletonAppService.GuidItem(); return View(); } } # Index View <div class="row"> <div > <h2>GuidItem Shows</h2> <h3>TransientItem: @ViewBag.TransientItem</h3> <h3>ScopedItem: @ViewBag.ScopedItem</h3> <h3>SingletonItem: @ViewBag.SingletonItem</h3> </div> </div>
以後咱們打開兩個瀏覽器,分別刷新數次,也只會發現「TransientItem」和「ScopedItem」的數值不斷變化,「SingletonItem」欄的數值是不會有任何變化的,這就體現出單例模式的做用了,示例圖以下函數
可是這好像還不夠,要知道咱們的Scoped的解讀是「生命週期橫貫整次請求」,可是如今演示起來和Transient好像沒有什麼區別(由於兩個頁面每次瀏覽器請求仍然是獨立的,並不包含於一次中),因此咱們採用如下代碼來演示下(同一請求源)
# 新建GuidItemPartial.cshtml視圖,複製以下代碼,使用@inject注入依賴 @using DependencyInjection.IApplicationService @inject IGuidTransientAppService TransientAppService @inject IGuidScopedAppService GuidScopedAppServic @inject IGuidSingletonAppService GuidSingletonAppService <div class="row"> <div> <h2>GuidItem Shows</h2> <h3>TransientItem: @TransientAppService.GuidItem()</h3> <h3>ScopedItem: @GuidScopedAppServic.GuidItem()</h3> <h3>SingletonItem: @GuidSingletonAppService.GuidItem()</h3> </div> </div> # 原先的index視圖 @{ ViewData["Title"] = "Home Page"; } @Html.Partial("GuidItemPartial") @Html.Partial("GuidItemPartial")
依然是 Ctrl+F5 調試運行,能夠發現「ScopedItem」在同一請求源中是不會發生變化的,可是「TransientItem」依然不斷變化,理論仍然是支持的
除了ASP.NETCore自帶的IOC容器外,咱們還可使用其餘成熟的DI框架,如Autofac,StructureMap等(筆者只用過Unity,Ninject和Castle,Castle也是使用ABP時自帶的)。
首先在project.json的dependency
節點中加入Autofac.Extensions.DependencyInjection
引用,目前最新版本是4.0.0-rc3-309
在Startup.cs中建立一個public IContainer ApplicationContainer { get; private set; }
對象,並把ConfigureServices
返回類型改成IServiceProvider
,而後複製如下代碼進去,也能夠實現相關功能
var builder = new ContainerBuilder(); //注意如下寫法 builder.RegisterType<GuidTransientAppService>().As<IGuidTransientAppService>(); builder.RegisterType<GuidScopedAppService>().As<IGuidScopedAppService>().InstancePerLifetimeScope(); builder.RegisterType<GuidSingletonAppService>().As<IGuidSingletonAppService>().SingleInstance(); builder.Populate(services); this.ApplicationContainer = builder.Build(); return new AutofacServiceProvider(this.ApplicationContainer);
值得注意的幾點:
ConfigureServices
的返回值修改成IServiceProvider