Many constructor implementations in a Unity container

For the following interfaces and classes, how can I use Unity Container to Fluently (programmatically), connect it so that FooController receives an instance of ARepository and BarController receives an instance of BRepository through constructor injection

 public interface IRepository { } public class ARepository : IRepository { } public class BRepository : ARepository { } public class FooController { public FooController(IService service, IRepository repository) { } } public class BarController { public BarController(IService service, IRepository repository) { } } 
+7
c # dependency-injection unity-container
source share
5 answers

I would highly recommend against creating a dedicated / local / injected UnityContainer for each type, such as the proposed poster.

There are two ways to approach this.

One of them is the specific definition of permission during registration, as suggested by Tyler Ollsen. This is a good solution, although if you later register both ARepository and BRepository as implementations for IRepository, you still have to deal with the fact that you have two implenetations for the same interface, and if the third class is something will require the implementation of IRepository, without defining it specifically during registration, it will receive an unpredictable instance.

The second option, which is slightly safer, registers the factory for IRepository. The simplest example would be to use a string as a key, for example:

 // Create a resolver(abstract factory) for the IRepository interface type var resolver = myContainer.Resolve<Func<IRepository>>(); // ... other code here... // Register mappings for the IRepository interface to appropriate concrete types myContainer.RegisterType<IRepository, ARepository>("A"); myContainer.RegisterType<IRepository, BRepository>("B"); 

Then, in the implementation of FooController and BarController, get the func factory by injection and select the correct instance.

 public class FooController { IRepository repository; public FooController(IService service, Func<IRepository> repositoryFactory) { repository = repositoryFactory("A"); } } 

You can read more about this here: http://msdn.microsoft.com/en-us/library/ff660854%28v=pandp.20%29.aspx

+3
source share

You can achieve this during registration by telling each controller registration how to enable its constructor parameters.

 container.RegisterType<FooController>(new InjectionConstructor( new ResolvedParameter<IService>(), new ResolvedParameter<ARepository>()); container.RegisterType<BarController>(new InjectionConstructor( new ResolvedParameter<IService>(), new ResolvedParameter<BRepository>()); 
+2
source share

You can register a type with a name and then use it in the Dependency attribute of the target classes:

 // Register mappings for the IRepository interface to appropriate concrete types myContainer.RegisterType<IRepository, ARepository>("A"); myContainer.RegisterType<IRepository, BRepository>("B"); 

Then in FooController and BarController, declare which implementation you require with the Dependency attribute:

 public class FooController { public FooController(IService service, [Dependency("A")] IRepository repository) { } } public class BarController { public BarController(IService service, [Dependency("B")] IRepository repository) { } } 

You can use public const string in ARepository and BRepository , rather than "A" and "B" both RegisterType and Dependency .

+2
source share

One possibility is to register a specific type that UnityContainer will resolve when IRepository :

 IUnityContainer container = new UnityContainer(); container.RegisterType<IRepository, BRepository>(new ContainerControlledLifetimeManager()); 

Using this depends on whether you require finer control over which types are allowed in certain contexts. If so, you can use a local instance of IUnityContainer and use RegisterInstance() instead:

 //Assumes container is instantiated and already populated with other instances/type mappings. IUnityContainer childContainer = container.CreateChildContainer(); container.RegisterInstance<IRepository>(new BRepository(), new ContainerControlledLifetimeManager()); 
+1
source share

JoefGoldstein delivered me most of the way, but when I tried this I got a few errors.

I had to register my classes with a named dependency and use the InjectionFactory class to resolve the dependency.

 // register interfaces to implementations with a named dependency myContainer.RegisterType<IRepository, ARepository>("A"); myContainer.RegisterType<IRepository, BRepository>("B"); // register Injection factory to resolve the dependency container.RegisterType<Func<string, IRepository>>( new InjectionFactory(c => new Func<string, IRepository>(name => c.Resolve<IRepository>(name))) ); 

Then in my controller

 public class FooController { IRepository repository; public FooController(IService service, Func<string, IRepository> repositoryFactory) { repository = repositoryFactory("A"); } } 
0
source share

All Articles