我在MVC应用程序(不是.Net Core应用程序,而是经典的ASP.NET MVC应用程序)中使用ASP.Net Core依赖注入。我通过添加Microsoft.Extensions.DependencyInjection Nuget包来使用DI。我正在尝试为控制器创建作用域生存期,因此每当我创建控制器时都会有一个新作用域,但是我总是为请求获取相同的实例,并且出现以下错误 “不能使用控制器'X.Controllers.HomeController'的单个实例来处理多个请求。如果正在使用自定义控制器工厂,请确保为每个请求创建一个新的控制器实例”。
我已经使用自定义工厂来创建控制器 并使用新的作用域创建控制器。 并将范围放置在ReleaseController方法中
public class MyServiceFactory : DefaultControllerFactory
{
private readonly IServiceContainer _dependencyManager;
public MyServiceFactory (IServiceContainer dependencyManager)
{
this._dependencyManager = dependencyManager;
}
public override void ReleaseController(IController controller)
{
_dependencyManager.Release(((ServiceEndPoint)controller).Context.RuntimeContext.Scope);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
var scope = _dependencyManager.GetNewScope();
var service=(ServiceEndPoint)_dependencyManager.Resolve(scope, controllerType);
service.Context.RuntimeContext.SetScope(scope);
return service;
}
}
ServiceEndpoint只是从Controller派生的基类,我将其用作我的所有控制器的基础,其中包含一些通用逻辑。 我正在为我的控制器设置一个上下文,该上下文也包含新创建的范围,并通过从上下文中获取它,将其放置在Releasecontroller中。 _dependencyManager.GetNewScope()创建一个如下所示的新范围
return _container.CreateScope();
_container是IServiceProvider的实例
代码_dependencyManager.Resolve(scope,type)如下
public object Resolve(IServiceScope scope,Type type)
{
return scope.ServiceProvider.GetService(type);
}
答案 0 :(得分:1)
您做错了事,但是当您在自己的抽象后面隐藏了Microsoft.Extensions.DependencyInjection(MS.DI)容器的使用时,无法看到正在发生的事情。
但是,以下是将ASP.NET MVC与MS.DI集成的工作示例应用程序的示例。
MS.DI专用控制器工厂:
public class MsDiControllerFactory : DefaultControllerFactory
{
private readonly ServiceProvider container;
public MsDiControllerFactory(ServiceProvider container) => this.container = container;
protected override IController GetControllerInstance(RequestContext c, Type type) =>
(IController)this.GetScope().ServiceProvider.GetRequiredService(type);
public override void ReleaseController(IController c) => this.GetScope().Dispose();
private IServiceScope GetScope() =>
(IServiceScope)HttpContext.Current.Items["scope"] ??
(IServiceScope)(HttpContext.Current.Items["scope"] = this.container.CreateScope());
}
MVC应用程序配置容器并替换默认控制器工厂:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Default MVC stuff
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// create container builder to register dependencies in
var services = new ServiceCollection();
// register controller in the controller
services.AddScoped<HomeController>();
// Build the container while ensuring scopes are validated
ServiceProvider container = services.BuildServiceProvider(true);
// Replace default controller factory
ControllerBuilder.Current.SetControllerFactory(
new MsDiControllerFactory(container));
}
}
将上述代码应用于使用Visual Studio的默认MVC模板创建的MVC应用程序时,您将获得一个使用MS.DI作为其应用程序容器的MVC应用程序。