Reputation: 5132
I have two implementations of an interface that in plain old c# would be instantiated like so:
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
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
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. 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?
Upvotes: 0
Views: 1045
Reputation: 5132
Registering types in Unity without a name makes that the default type. 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:
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>();
}
}
Upvotes: 1
Reputation: 4489
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. When you need the oven you can call _ovenFactory.Create()
.
In an IOvenFactory
implementation, you could have the logic of how to create, depending on the configuration value.
Upvotes: 0