Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor injection multiple implementations in Unity Container [duplicate]

For the following interfaces and classes, how do I use Unity Container to Fluently (programatically) wire it up so that FooController gets an instance of ARepository and BarController gets an instance of BRepository via 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)
    {
    }
}
like image 693
Sebastian Patten Avatar asked Dec 19 '14 15:12

Sebastian Patten


People also ask

CAN interface have multiple implementations C#?

Using the delegate func Introduce three implementation classes as below- three different classes where we have implemented the same interface. ASP.NET Core has built-in support for dependency injection. However, multiple implementations of an interface in ASP.NET Core is tricky.

What is Injectionconstructor?

A class that holds the collection of information for a constructor, so that the container can be configured to call this constructor.

What is Injectionfactory?

A class that lets you specify a factory method the container will use to create the object.

What is dependency injection stack overflow?

Dependency injection is a pattern to allow your application to inject objects on the fly to classes that need them, without forcing those classes to be responsible for those objects. It allows your code to be more loosely coupled, and Entity Framework Core plugs in to this same system of services.


2 Answers

You can achieve this at registration time by telling each controller registration how to resolve 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>());
like image 160
TylerOhlsen Avatar answered Oct 05 '22 21:10

TylerOhlsen


I would highly recommend against creating a dedicated/local/injected UnityContainer for each type like one of the posters suggested.

This can be approached in two ways.

One is by specifically defining the resolving in registration time as TylerOhlsen suggested. This is a good solution, though if you register later both ARepository and BRepository as implementations for IRepository, you still need to deal with the fact you have two implenetations for the same interface, and if a third class will someday require an implementation of IRepository, without defining it specifically in the registration, it will get an unpredictable instance.

The second option, which is slightly safer, is registering a factory for IRepository. The simplest example would be using a string as the key, like this:

// 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 receive the func factory by injection and select the right 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

like image 44
JoefGoldstein Avatar answered Oct 05 '22 23:10

JoefGoldstein