Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity Register For One Interface Multiple Object and Tell Unity Where to Inject them

Hi I have been having trouble trying to tell Unity that for an Interface if it has multiple implementations , I want it to inject them in different classes.Here is what I mean:

Let's say I have an interface IProductCatalogService and two implementations ProductCatalog : IProductCatalogService and ProductCatalogService : IProductCatalogService.

How would I go about telling Unity that for Class A I want in my constructor passed an instance of type ProductCatalog and for Class B I want an instance of ProductCatalogService.

I am using Unity in an ASP.NET Web API project and I have set the resolver in the GLobalConfiguration.

For simple 1 to 1 registrations everything works.

Here is what I have tried but it does not seem to work:

public class DependencyServiceModel
{
    public Type From { get; set; }
    public Type To { get; set; }
    public IEnumerable<Type> ForClasses { get; set; }
}

public void RegisterTypeForSpecificClasses(DependencyServiceModel dependencyService)
{
    foreach (var forClass in dependencyService.ForClasses)
    {
        string uniquename = Guid.NewGuid().ToString();

        Container.RegisterType(dependencyService.From, 
            dependencyService.To, uniquename);

        Container.RegisterType(forClass, uniquename, 
            new InjectionConstructor(
                new ResolvedParameter(dependencyService.To)));
    }
}

In the DependencyServiceModel, From is the interface, To is the object to witch I want to instantiate and ForClasses are the Type for which I want to use the To Object.

like image 678
aleczandru Avatar asked Sep 06 '13 19:09

aleczandru


People also ask

What is Injectionfactory?

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

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.

How do I register a type with Unity container?

Before Unity resolves the dependencies, we need to register the type-mapping with the container, so that it can create the correct object for the given type. Use the RegisterType() method to register a type mapping. Basically, it configures which class to instantiate for which interface or base class.

What is Iunitycontainer?

The Unity Container (Unity) is a full featured, extensible dependency injection container. It facilitates building loosely coupled applications and provides developers with the following advantages: Simplified object creation, especially for hierarchical object structures and dependencies.


2 Answers

Nice to know. If you register multiple types to an Interface like belove;

container.RegisterType<ITransactionsService, EarningsManager>();
container.RegisterType<ITransactionsService, SpendingsManager>();

you can not get the list of types by;

IEnumerable<ITransactionsService> _transactionsService;

here in the list will be always the last registered type ( SpendingsManager.)

To prevent this situation ;

container.RegisterType<ITransactionsService, EarningsManager>("EarningsManager");
container.RegisterType<ITransactionsService, SpendingsManager>("SpendingsManager");

You have to change the code in this way.

like image 149
Doğuhan Yangöz Avatar answered Sep 18 '22 12:09

Doğuhan Yangöz


In the example below you have an interface implemented twice and injected on demand into two different client classes, just as you request. The trick is to use named registrations.

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<IFoo, Foo1>("Foo1");
        container.RegisterType<IFoo, Foo2>("Foo2");

        container.RegisterType<Client1>(new InjectionConstructor(new ResolvedParameter<IFoo>("Foo1")));
        container.RegisterType<Client2>(new InjectionConstructor(new ResolvedParameter<IFoo>("Foo2")));

        Client1 client1 = container.Resolve<Client1>();
        Client2 client2 = container.Resolve<Client2>();
    }
}

public interface IFoo
{

}

public class Foo1 :IFoo
{

}

public class Foo2 : IFoo
{

}

public class Client1
{
    public Client1(IFoo foo)
    {

    }
}

public class Client2
{
    public Client2(IFoo foo)
    {

    }
}

This is most probably what you do wrong:

 Container.RegisterType(forClass, uniquename, 
        new InjectionConstructor(
            new ResolvedParameter(dependencyService.To)));

You create a named registration for your concrete class. Instead you should have

 Container.RegisterType(forClass, null, 
        new InjectionConstructor(
            new ResolvedParameter(dependencyService.To, uniquename)));
like image 29
Wiktor Zychla Avatar answered Sep 19 '22 12:09

Wiktor Zychla