<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在 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
;不過我找不到任何理由,這兩點實現還不能滿足您的需求!
IControllerActivator
設定為DefaultControllerActivator
。DefaultControllerActivator
使用TypeActivatorCache
來建立控制器。它從 DI 容器載入建構函式所需引數來建立控制器的範例。ServiceBasedControllerActivator
作替代方法,它直接從 DI 容器載入控制器。您可以在Startup.ConfigureServices
方法中使用MvcBuilder
的AddControllersAsServices()
擴充套件方法來設定此啟用方式。到此這篇關於ASP.NET Core MVC建立控制器與依賴注入的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45