如何将命名依赖项注入控制器?

How do I inject named dependencies in to a controller?

我创建了一个配置了 Unity MVC 和 Unity Web API 的 C# ASP 项目。

我不想在依赖于它们的对象中定义 名称 依赖项 - 我试图将该配置与其他容器配置放在一起。

但我正在努力确定如何使用控制器来做到这一点?我的控制器看起来像:

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();
        }
    }
}

我目前对容器配置的尝试如下:

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")
    )));

但我最终遇到了这个例外:

The current type, MyService.App_Start.ITest, is an interface and cannot be constructed. Are you missing a type mapping?

这对我来说意味着它没有使用容器来获取注册的 HomeController。我不确定如何正确连接它?

解决方案

采用公认的答案,对我有用的确切解决方案是注册这个控制器工厂;

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;
    }
}

在 Start() 中使用这个来实际注册它,当然:

ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));

MVC 中的控制器是由控制器工厂创建的。如果你想要用户依赖注入,你必须挂钩到这个控制器工厂并进行你的覆盖,这将使用统一。

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);
  }
}

在global.asax.cs中:

protected void Application_Start() {
  // initialization of unity container
  ServiceLocator.IoC = ...; 
  var factory = new MgsMvcControllerFactory()
  ControllerBuilder.Current.SetControllerFactory(factory);
}

另一种选择(恕我直言)是创建基础 Controller - 我们称它为 DIController,它将在构造函数中调用 BuildUp() 并从此 [= 继承其余控制器13=]。不用说,您必须将基于构造函数的注入重写为方法或基于 属性 的注入。