简体   繁体   English

如何指定与特定MVC控制器一起使用的接口注册?

[英]How do I specify which registration of an interface to use with a particular mvc controller?

I have two implementations of an interface that in plain old c# would be instantiated like so: 我有一个接口的两种实现,在普通的老式C#中将像这样实例化:

var useCache = bool.Parse(ConfigurationManager.AppSettings["useCache"]);
var oven = useCache
  ? new CachedCookieOven(new CookieOven())
  : new CookieOven();
var controller = new CookieController(oven); // MVC Controller

here is the interface and classes: 这是接口和类:

public interface ICookieOven {
  IEnumerable<Cookie> Bake();
}

public class CookieOven : ICookieOven {
  public IEnumerable<Cookie> Bake() {
    var list = new List<Cookie>();
    // bake cookies and return them
    return list;
  }
}

public class CachedCookieOven : ICookieOven {
  readonly ICookieOven _oven;

  public CachedCookieOven(ICookieOven oven) { _oven = oven; }

  public IEnumerable<Cookie> Bake() {
    var cookies = GetFromPlate();
    return cookies ?? _oven.Bake();
  }
}

My MVC controller has the following constructor 我的MVC控制器具有以下构造函数

public class CookieController : Controller {

  readonly ICookieOven _oven;

  public CookieController(ICookieOven oven) { _oven = oven; }

  public ActionResult ViewCookies() {
    var bakedCookies = _oven.Bake();
    return View(bakedCookies);
  }
}

The Bootstrapper class that is created says in the comments that I don't need to register my mvc controller classes 创建的Bootstrapper类在注释中说,我不需要注册我的mvc控制器类。

public static class Bootstrapper
{
    public static IUnityContainer Initialise()
    {
        var container = BuildUnityContainer();

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();    
        RegisterTypes(container);

        return container;
    }

    public static void RegisterTypes(IUnityContainer container)
    {

    }
}

In Unity I have registered both instances. 在Unity中,我已经注册了两个实例。 There may be a better way and if so tell me. 可能有更好的方法,如果可以,请告诉我。

public static class Bootstrapper {
  // ...
  private static IUnityContainer BuildUnityContainer() {
    var container = new UnityContainer();
    var useCache = bool.Parse(ConfigurationManager.AppSettings["useCache"]);
    // register
    container.RegisterType<ICookieOven, CookieOven>("oven");
    if (useCache) {
      container.RegisterType<ICookieOven, CachedCookieOven>("cachedOven",
        new InjectionConstructor(container.Resolve<ICookieOven>("oven"));
    }

  }
}

How do I ensure that the correct instance of ICookieOven gets sent to the constructor of the CookieController mvc controller? 如何确保将正确的ICookieOven实例发送到CookieController mvc控制器的构造函数?

Registering types in Unity without a name makes that the default type. 在没有名称的Unity中注册类型会使其成为默认类型。 If you want to register more than one type, you have to provide a name. 如果要注册多个类型,则必须提供一个名称。 The following is the correct way to register my types in the Bootstrapper class: 以下是在Bootstrapper类中注册我的类型的正确方法:

public static void RegisterTypes(IUnityContainer container)
{
  var useCache = bool.Parse(ConfigurationManager.AppSettings["useCache"]);
  if (useCache) { 
    // named, this is not the default
    container.RegisterType<ICookieOven,CookieOven>("oven");
    // this one is not named and is the default
    container.RegisterType<ICookieOven,CachedCookieOven>(new InjectionConstructor(
      container.Resolve<ICookieOven>("oven")); 
  } else {
    // notice it is not named, it is the default
    container.RegisterType<ICookieOven,CookieOven>();
  }
}

You want to create an object but which one depends on a value only known at runtime. 您想创建一个对象,但是哪个对象取决于仅在运行时才知道的值。 What you need is a factory (couple of examples here ). 您需要的是一个工厂( 这里有几个示例)。

To implement this, one approach could be like this: your controller could depend on a IOvenFactory , injected in controller's constructor. 为了实现这一点,一种方法可能是这样的:您的控制器可能依赖于IOvenFactory ,注入到控制器的构造函数中。 When you need the oven you can call _ovenFactory.Create() . 当您需要烤箱时,可以调用_ovenFactory.Create()

In an IOvenFactory implementation, you could have the logic of how to create, depending on the configuration value. IOvenFactory实现中,您可以根据配置值掌握如何创建的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM