Unity - how to use multiple mappings for the same type and inject into an object
Asked Answered
L

1

4

I'm using Unity 2.0 and in the following code I'm trying to inject a specific tool in the Worker object.

I would like to use the following code. But ofcourse there is an error "Resolution of the dependency failed". I believe I should be able to do something like this, but I'm having a difficult time figuring it out.

IUnityContainer container = new UnityContainer();
container.RegisterType<IWorker, Worker>("Worker")
    .RegisterType<ITool, ToolA>("ToolA")
    .RegisterType<ITool, ToolB>("ToolB")
    .RegisterType<ITool, ToolC>("ToolC");

IWorker worker = container.Resolve<Worker>("ToolA");

I know this doesn't work, but how would I resolve this issue?

BarDev

Lunseth answered 26/3, 2011 at 7:6 Comment(0)
C
9

There are two ways you can achieve this:

You can use ParameterOverride's and a two step resolution process...

var tool = container.Resolve<ITool>("ToolB");
var worker = container.Resolve<IWorker>("Worker", 
    new ParameterOverride("tool", tool));

...assuming that the constructor argument on Worker that receives the ITool is called 'tool' (multiple ParameterOverride instances can be passed to Resolve). Any other dependencies (via constructor or property injection) that the named instance of IWorker has should be correctly resolved as well.

Alternatively, why not setup named WorkerA, WorkerB, WorkerC instances that require the specified ITool...

container.RegisterType<ITool, ToolA>("ToolA");
container.RegisterType<ITool, ToolB>("ToolB");
container.RegisterType<ITool, ToolC>("ToolC");
container.RegisterType<IWorker, Worker>("WorkerA", 
    new InjectionConstructor(new ResolvedParameter<ITool>("ToolA")));
container.RegisterType<IWorker, Worker>("WorkerB", 
    new InjectionConstructor(new ResolvedParameter<ITool>("ToolB")));
container.RegisterType<IWorker, Worker>("WorkerC", 
    new InjectionConstructor(new ResolvedParameter<ITool>("ToolC")));

The disadvantage I suppose with the latter approach is that if Worker takes additional constructor parameters you will need to specify them to the InjectionConstructor as well, specified in the same order as the constructor you are expecting Unity to use...

container.RegisterType<IWorker, Worker>("WorkerA", 
    new InjectionConstructor(typeof(SomeDependency), new ResolvedParameter<ITool>("ToolA"), typeof(SomeOtherDependency));

However, Unity will lookup the non-named instance of SomeDependency and SomeOtherDependency in the above example, so that saves you a bit of work.

Crookback answered 26/3, 2011 at 7:28 Comment(3)
Sweat, this is great. This was the piece of the puzzle that I was missing. Now everything is coming together.Lunseth
Out of interest, which approach works best for you? In a project I am working, I find uses for both of these approaches actually.Crookback
The second options helps me alot. The application I'm working on finds classes from dynamicly loaded assemblies that match an interface. I create the registration for the tool and then create the registration for the worker and specify the tool for the worker. Its 1 to 1 mapping. I also have other construction paramerter that I'm passing in to both objects. I'm also able to implement Policy Injection for AOP task. This has help me a lot.Lunseth

© 2022 - 2024 — McMap. All rights reserved.