您好,登錄后才能下訂單哦!
這篇文章主要介紹“ASP.NET Core MVC如何創建控制器與依賴注入”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“ASP.NET Core MVC如何創建控制器與依賴注入”文章能幫助大家解決問題。
在 ASP.NET Core 中,當 MVC 中間件接收到請求時,通過路由選擇要執行的控制器和操作方法。為了實際的執行操作, MVC 中間件必須創建所選控制器的實例。
創建控制器的過程依賴眾多不同的提供者和工廠類,但最終是由實現IControllerActivator
接口的實例來決定的。實現類只需要實現兩個方法:
public interface IControllerActivator { object Create(ControllerContext context); void Release(ControllerContext context, object controller); }
如您所見,該IControllerActivator.Create
方法傳遞了用于創建控制器的ControllerContext
實例。控制器的創建方式取決于具體的實現。
眾所周知,ASP.NET Core 使用的是DefaultControllerActivator
,它通過TypeActivatorCache來創建控制器。TypeActivatorCache
通過調用類的構造函數,并試圖從 DI 容器中解析構造函數所需參數的實例。
有一點很重要,DefaultControllerActivator
不會試圖從 DI 容器中解析控制器的實例,只會解析控制器的依賴項。
為了演示這個行為,我創建了一個簡單的 MVC 應用程序,包括一個單一的服務和一個控制器。服務實例有一個name屬性,它通過構造函數來設置。默認情況下,它使用"default"
作為默認值。
public class TestService { public TestService(string name = "default") { Name = name; } public string Name { get; } }
在應用程序中HomeController
依賴于TestService
,并返回Name
屬性的值:
public class HomeController : Controller { private readonly TestService _testService; public HomeController(TestService testService) { _testService = testService; } public string Index() { return "TestService.Name: " + _testService.Name; } }
還有一塊代碼在Startup
文件中。在這里我將TestService
注冊在 DI 容器中作為范圍內服務,并設置 MVC 中間件和服務:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddScoped<TestService>(); services.AddTransient(ctx => new HomeController(new TestService("Non-default value"))); } public void Configure(IApplicationBuilder app) { app.UseMvcWithDefaultRoute(); } }
您會注意到,我定義了一個工廠方法用于創建HomeController
的實例。將HomeController
類型注冊到 DI 容器中,并且在TestService
實例中傳遞自定義Name
屬性。
如果您運行應用程序,您會看到什么結果?
您可以看到,該TestService.Name
屬性使用的是默認值,表示TestService
實例是直接從 DI 容器中獲取的,直接忽略了創建HomeController
的工廠方法。
這很容易理解,當您通過DefaultControllerActivator
創建控制器時,它不會從DI容器中創建HomeController
實例,只會解析構造函數的依賴項。
大多數情況下,使用DefaultControllerActivator
是一個不錯的選擇,但有時您可能希望直接通過 DI 容器來創建控制器,比如您希望使用具有攔截器或裝飾器等功能的第三方容器。
幸運的是,MVC 框架包含了一個這樣的IControllerActivator
實現,并提供了一種非常方便的擴展方法來啟用它。
如您所見,DefaultControllerActivator
使用TypeActivatorCache
來創建控制器,MVC還包括另一個實現,稱為 ServiceBasedControllerActivator
,它是直接從 DI 容器中獲取控制器。它的實現非常簡單:
public class ServiceBasedControllerActivator : IControllerActivator { public object Create(ControllerContext actionContext) { var controllerType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType(); return actionContext.HttpContext.RequestServices.GetRequiredService(controllerType); } public virtual void Release(ControllerContext context, object controller) { } }
當您將 MVC 服務添加到應用程序時,可以使用AddControllersAsServices()
擴展方法配置基于 DI 的激活器:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddControllersAsServices(); services.AddScoped<TestService>(); services.AddTransient(ctx => new HomeController(new TestService("Non-default value"))); } public void Configure(IApplicationBuilder app) { app.UseMvcWithDefaultRoute(); } }
通過上面的代碼,點擊主頁將通過 DI 容器來創建一個控制器。由于我們已經注冊了一個創建HomeController
的工廠方法,我們自定義TestService
配置將被保留,使用替換后的Name
屬性:
AddControllersAsServices
方法實現了兩件事情 - 它將您應用程序中的所有控制器注冊到 DI 容器(如果尚未注冊),并將IControllerActivator
注冊為ServiceBasedControllerActivator
:
public static IMvcBuilder AddControllersAsServices(this IMvcBuilder 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<IControllerActivator, ServiceBasedControllerActivator>()); return builder; }
如果需要做一些更復雜的事情,您可以隨時實現自己IControllerActivator
;不過我找不到任何理由,這兩點實現還不能滿足您的需求!
關于“ASP.NET Core MVC如何創建控制器與依賴注入”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。