97

I am using Microsoft's Unity for dependency injection and I want to do something like this:

IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context
IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);

RepositoryA and RepositoryB both have a constructor that takes an IDataContext parameter, and I want Unity to initialize the repository with the context that I pass it. Also note that IDataContext is not registered with Unity (I don't want 3 instances of IDataContext).

Vivek Jain
3,8856 gold badges33 silver badges47 bronze badges
asked Apr 24, 2009 at 18:18

8 Answers 8

73

As of today they have added this functionality:

It’s in the latest drop here:

http://unity.codeplex.com/SourceControl/changeset/view/33899

Discussion on it here:

http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434

Example:

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"
answered Sep 21, 2009 at 23:52
Sign up to request clarification or add additional context in comments.

6 Comments

"Class 'Microsoft.Practices.Unity.ParameterOverrides' does not have type parameters". I'm using Unity 3.5; is this code valid only for an older version of Unity?
It works for me. Note: Your class must have a parametrized constructor with "name" parameter and "address" parameter. Foo(string name, int address) { ... }
Using Unity 2.1: container.Resolve<IFoo>(new ParameterOverrides { { "name", "bar" }, { "address", 42 } });
|
39

< 2 cents>

What if you later on decide to use a different service that requires more or less than just the context?

The problem with constructor parameters and IoC is that the parameters are ultimately tied to the concrete type being used, as opposed to being part of the contract that the service interface defines.

My suggestion would be that you either resolve the context as well, and I believe Unity should have a way for you to avoid constructing 3 instances of it, or you should consider a factory service that has a way for you to construct the object.

For instance, what if you later on decide to construct a repository that doesn't rely on a traditional database at all, but instead use an XML file to produce dummy-data for the test? How would you go about feeding the XML content to that constructor?

IoC is based around decoupling code, by tying in the type and semantics of the arguments to the concrete types, you really haven't done the decoupling correctly, there's still a dependency.

"This code can talk to any type of repository possibly, as long as it implements this interface.... Oh, and uses a data context".

Now, I know that other IoC containers have support for this, and I had it in my first version of my own as well, but in my opinion, it doesn't belong with the resolution step.

< /2 cents>

answered Apr 24, 2009 at 18:48

2 Comments

I see your point and agree with you, however I still need the RepositoryA and RepositoryB's instances to have the same IDataContext, which needs to be different than RepositoryC. Also note that IRepositoryA and IRepositoryB has a property for IDataContext. I'll update the sample code a bit.
Great point. I was about to add a string parameter to the constructor, but after viewing this point, i decided to make it a full blown object. It only consists of the string at this point, but i can already see how I could add more useful properties to it
11

Thanks guys ... mine is similar to the post by "Exist". See below:

 IUnityContainer container = new UnityContainer();
 container.LoadConfiguration();
 _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
 {
 new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
 });
answered Oct 29, 2014 at 15:43

Comments

4

You can use InjectionConstructor / InjectionProperty / InjectionMethod depending on your Injection Architecture within the ResolvedParameter< T>("name") to get a instance of a pre-registered Object in the container.

In your case this Object must be registered with a Name, and for the same insance you need ContainerControlledLifeTimeManager() as the LifeTimeManager.

_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");
 var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));
 var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));
 var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));
answered Apr 28, 2010 at 19:02

2 Comments

Are you sure about this code? It doesn't compile... Resolve takes a collection of ResolverOverride, and InjectionConstructor isn't a ResolverOverride.
Yup It looks wrong. Although unity should have designed it that way. If parameter name changes everything breaks
3

The very short answer is: no. Unity currently has no way to pass parameters into the constructor that aren't constant or injected, that I have been able to find. IMHO that's the single biggest thing it's missing, but I think it is by design rather than by omission.

As Jeff Fritz notes, you could in theory create a custom lifetime manager that knows which context instance to inject into various types, but that's a level of hard-coding which seems to obviate the purpose of using Unity or DI in the first place.

You could take a small step back from full DI and make your repository implementations responsible for establishing their own data contexts. The context instance can still be resolved from the container but the logic for deciding which one to use would have to go into the implementation of the repository. It's not as pure, certainly, but it would get rid of the problem.

answered Apr 29, 2009 at 12:54

Comments

1

Another alternative you could use (don't really know if it is a good practice or not) is creating two containers and registering an instance for each:

IDataContext context = _unityContainer.Resolve<IDataContext>();
_unityContainer.RegisterInstance(context);
var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context
//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance

hope this helps too

answered May 15, 2009 at 12:02

Comments

0

NotDan, I think you may have answered your own question in comments to lassevk.

First, I would use a LifetimeManager to manage the lifecycle and number of instances of IDataContext that Unity creates.
http://msdn.microsoft.com/en-us/library/cc440953.aspx

It sounds like the ContainerControlledLifetimeManager object will give you the instance management that you need. With that LifetimeManager in place, Unity should add the same instance of the IDataContext to all objects that require an IDataContext dependency.

answered Apr 28, 2009 at 10:18

Comments

0

Almost 15 years later I was still looking for a definitive answer on how to Resolve a class which requires a string to be passed into the constructor.

I found that definitive answer in the UnityContainter.org docs here in the quickstart info.

Here's the explanation of how Unity picks a particular Constructor when the constructor is overloaded.

It will create any type with accessible constructor. Consider following example:

// Simple class Foo
public class Foo
{
 public Foo() { }
 public Foo(object obj) { }
 public Foo(string id, object obj) { }
}
// Create container
IUnityContainer container = new UnityContainer();
// Resolve Foo
var value = container.Resolve<Foo>();
// value created with constructor 'Foo(object obj)'

Foo is a simple class with three public constructors. When Resolve() is called, Unity will evaluate available constructors and select one with longest list of parameters it can satisfy with dependencies. It will create all required dependencies and pass them to selected constructor during initialization.

In this particular case Unity will select second constructor with parameter obj of type Object. Although constructor Foo(string id, object obj) is longer, it has parameter of type String which is a primitive type. Unity can not create primitive types by itself. If you want to make these available for dependency injection you would need to register them with the container. For Unity to select third constructor Foo(string id, object obj) you need to register string instance with container:

// Register string instance
container.RegisterInstance("xyz");
// Resolve Foo
var value = container.Resolve<Foo>();
// value created with constructor 'Foo(string id, object obj)'
answered Feb 11, 2024 at 16:48

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.