日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core MVC 控制器创建与依赖注入

發布時間:2023/12/4 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core MVC 控制器创建与依赖注入 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在我最后一篇關于 ASP.NET Core 釋放IDsiposable對象的文章(中文、英文原文)中,Mark Rendle?指出,MVC 控制器在請求結束時也會釋放資源。乍一看,此范圍內的資源在請求結束時會釋放似乎是顯而易見的,但是 MVC 控制器的處理方式實際上與大多數服務略有不同。

在這篇文章中,我將介紹在ASP.NET Core MVC中IControllerActivator是如何創建控制器的,以及通過依賴注入創建控制器存在的差異。

默認的IControllerActivator

在 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 容器中解析控制器的實例,只會解析控制器的依賴項。


DefaultControllerActivator 示例

為了演示這個行為,我創建了一個簡單的 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實現,并提供了一種非常方便的擴展方法來啟用它。


ServiceBasedControllerActivator

如您所見,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 中IControllerActivator配置為DefaultControllerActivator。

  • DefaultControllerActivator使用TypeActivatorCache來創建控制器。它從 DI 容器加載構造函數所需參數來創建控制器的實例。

  • 您也可以使用ServiceBasedControllerActivator作替代方法,它直接從 DI 容器加載控制器。您可以在Startup.ConfigureServices方法中使用MvcBuilder的AddControllersAsServices()擴展方法來配置此激活方式。

原文地址:http://www.cnblogs.com/tdfblog/p/controller-activation-and-dependency-injection-in-asp-net-core-mvc.html


.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

總結

以上是生活随笔為你收集整理的ASP.NET Core MVC 控制器创建与依赖注入的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。