如何指定接口的哪个注册用于特定的mvc控制器



我有两个接口的实现,在普通的旧c#中,它会被实例化为这样:

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

这是接口和类:

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

我的MVC控制器有以下构造函数

public class CookieController : Controller {
  readonly ICookieOven _oven;
  public CookieController(ICookieOven oven) { _oven = oven; }
  public ActionResult ViewCookies() {
    var bakedCookies = _oven.Bake();
    return View(bakedCookies);
  }
}

创建的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)
    {
    }
}

在Unity,我已经登记了这两种情况。可能有更好的方法,如果是的话,告诉我。

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

如何确保ICookieOven的正确实例被发送到CookieController mvc控制器的构造函数?

在Unity中注册没有名称的类型会使其成为默认类型。如果要注册多个类型,则必须提供名称。以下是在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>();
  }
}

您想要创建一个对象,但哪个对象取决于仅在运行时已知的值。你需要的是一个工厂(这里有几个例子)。

要实现这一点,有一种方法可以是这样的:您的控制器可以依赖于在控制器的构造函数中注入的IOvenFactory。当你需要烤箱的时候,你可以打电话给_ovenFactory.Create()

IOvenFactory实现中,您可以根据配置值获得如何创建的逻辑。

最新更新