user3043457
user3043457

Reputation: 533

Resolving two instances of the same interface

If I have two classes of the same interface, and a constructor that takes two different versions of it - how can I use Unity container to resolve the dependencies?

Here's a simple test:

class Dependant
{
    public Dependant(ILog dbLog, ILog fsLog)
    {
        foreach (var i in Enumerable.Range(1, 15))
        {
            if (i%3 == 0)
                dbLog.Log(string.Format("{0} - going to DB", i));
            else
                fsLog.Log(string.Format("{0} - going to FS", i));
        }   
    }
}

Now, I'd like to use container to resolve dependencies. I tried this:

static void Main(string[] args)
{
    var container = new UnityContainer();

    container.RegisterType<ILog, DatabaseLogger>();
    container.RegisterType<ILog, FileLogger>();

    var dependant = container.Resolve<Dependant>();
}

But when the Dependant is resolved with two instances of FileLogger. I tried to give names to registration, to match the names used by the constructor but that didn't work.

Upvotes: 3

Views: 934

Answers (3)

jgauffin
jgauffin

Reputation: 101150

Change the constructor so that you take in a array instead:

class Dependant
{
    public Dependant(ILog[] logs)
    {
        foreach (var i in Enumerable.Range(1, 15))
        {
            foreach (var log in logs)
                log.Log(string.Format("{0} - going to FS", i));
        }   
    }
}

Upvotes: 0

Horizon_Net
Horizon_Net

Reputation: 5979

You can register/resolve two implementation of the same interface using named components. For your example it would look similar to the following

var container = new UnityContainer();

container.RegisterType<ILog, DatabaseLogger>("databaseLogger");
container.RegisterType<ILog, FileLogger>("fileLogger");

container.RegisterType<Dependant>(new InjectionConstructor(
                                  new ResolvedParameter<ILog>("databaseLogger"),
                                  new ResolvedParameter<ILog>("fileLogger")));

var dependant = container.Resolve<Dependant>();

You can also register your database logger as the default if you leave out the naming, f.e.

container.RegisterType<ILog, DatabaseLogger>();
container.RegisterType<ILog, FileLogger>("fileLogger");

In that case resolving ILog would use your DatabaseLogger. So there's no need to define more interfaces as needed.

EDIT

I modified the code snippet above, because I think it better fits your needs.

Upvotes: 5

dbugger
dbugger

Reputation: 16399

Create a separate interface for each one -- since you are using them separately in your application anyway. They can both inherit from ILog if you need to use them polymorphically but just making two different interfaces will let Unity resolve them for your constructor.

public interface IDatabaseLog: ILog
{
}

public interface IFileLog: ILog
{
}

public class DatabaseLogger: IDatabaseLog
{
}

public class FileLogger: IFileLog
{

}

public Dependant(IDatabaseLog dbLog, IFileLog fsLog)
{
 //useful code
}

Upvotes: 4

Related Questions