Reputation: 533
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
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
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
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