数据网站建设哪家好,网站验证码是如何做的,dw友情链接怎么设置,网页设计实训报告2000字通用在我最后一篇关于 ASP.NET Core 释放IDsiposable对象的文章#xff08;中文、英文原文#xff09;中#xff0c;Mark Rendle 指出#xff0c;MVC 控制器在请求结束时也会释放资源。乍一看#xff0c;此范围内的资源在请求结束时会释放似乎是显而易见的#xff0c;但是 MV…在我最后一篇关于 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.AddScopedTestService();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.AddScopedTestService();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.TransientIControllerActivator, 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跨平台或扫描二维码关注