[英]How do I inject named dependencies in to a controller?
I've created a C# ASP project with Unity MVC and Unity Web API configured. 我创建了一个配置了Unity MVC和Unity Web API的C#ASP项目。
I don't want to define the names of dependencies in objects which depend on them - I'm trying to keep that configuration alongside the other container configuration. 我不想在依赖它们的对象中定义依赖项的名称 -我正在尝试将该配置与其他容器配置一起保留。
But I'm struggling to determine how to do that with controllers? 但是我正在努力确定如何使用控制器来做到这一点? My controller looks like:
我的控制器看起来像:
namespace MyService.Controllers
{
public class HomeController : Controller
{
private ITest test;
public HomeController(ITest test)
{
this.test = test;
}
public ActionResult Index()
{
ViewBag.Title = "Home Page";
return View();
}
}
}
And my current attempt at container configuration looks like: 我目前对容器配置的尝试如下所示:
container.RegisterType<ITest>("bar",
new InjectionFactory(c => new TestImpl1()));
container.RegisterType<ITest>("foo",
new InjectionFactory(c => new TestImpl2()));
container.RegisterType<HomeController>("Home",
new InjectionFactory(c => new HomeController(
c.Resolve<ITest>("foo")
)));
But I end up with this exception: 但是我最终遇到了这个异常:
The current type, MyService.App_Start.ITest, is an interface and cannot be constructed. Are you missing a type mapping?
Which implies to me that it's not using the container to get the registered HomeController. 在我看来,这不是在使用容器来获取注册的HomeController。 I'm not sure how to wire this up correctly?
我不确定如何正确连接吗?
Solution 解
Taking the accepted answer, the exact solution which worked for me is registering this controller factory; 采取公认的答案,对我有用的确切解决方案是在该控制器工厂注册;
public class UnityControllerFactory : DefaultControllerFactory
{
private readonly IUnityContainer _container;
public UnityControllerFactory(IUnityContainer container)
{
_container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return base.GetControllerInstance(requestContext, null);
}
return _container.Resolve(controllerType) as IController;
}
}
With this in Start() to actually register it, of course: 当然,使用Start()中的这个来实际注册它:
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
Controllers in MVC are created by controller factory. MVC中的控制器由控制器工厂创建。 If you want to user dependency injection, you have to hook to this controller factory and make your override that will make use of unity.
如果要进行用户依赖性注入,则必须挂接到该控制器工厂,并进行覆盖以使用统一性。
public class MgsMvcControllerFactory : DefaultControllerFactory {
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
// our controller instance will have dependency injection working
if (!ServiceLocator.IoC.IsServiceRegistered(controllerType, controllerType.FullName)) {
ServiceLocator.IoC.RegisterType(controllerType, controllerType.FullName, new ContainerControlledLifetimeManager())
}
return ServiceLocator.IoC.Resolve<IController>(controllerType.FullName);
}
}
And in global.asax.cs: 在global.asax.cs中:
protected void Application_Start() {
// initialization of unity container
ServiceLocator.IoC = ...;
var factory = new MgsMvcControllerFactory()
ControllerBuilder.Current.SetControllerFactory(factory);
}
Alternative (lot less cool IMHO) is creation of base Controller
- let's call it DIController
that will call BuildUp()
in constructor and inherit rest of the controllers from this DIController
. 替代方案(不太酷的IMHO)是创建基本
Controller
-称之为DIController
,它将在构造函数中调用BuildUp()
并从该DIController
继承其余的控制器。 Needless to say you'll have to rewrite constructor based injection to method or property based injection. 不用说,您将不得不将基于构造函数的注入重写为基于方法或基于属性的注入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.