Unity: how to specify the use of a specific instance of a type when resolving another type

I am trying to do the following in Unity:

I have a type with the following constructor

public Type1(Type2 firstDependency, Type3 secondDependency) 

When resolving Type1 using Unity, I want to specify a specific instance for Type2 for input. This particular Type2 instance Type2 not registered in the container. Type3 registered in the container and should be resolved as usual.

To be more specific, consider Type1 , the DocumentViewer class. Type2 is a specific Document . Type3 is SpellingChecker .

I want to enable a DocumentViewer for a Document that is known only at runtime. You can create multiple instances of DocumentViewer for differenct Documents .

How can i do this?

+6
c # unity-container
source share
6 answers

Here is a quick example I made, you use RegisterInstance or you can use Claas lifecycle management

 static void Main(string[] args) { IUnityContainer container = new UnityContainer(); container.RegisterType<Type1>(); container.RegisterInstance<Type2>(new Type2()); Type1 t = container.Resolve<Type1>(); Type2 t2 = container.Resolve<Type2>(); Type3 t3 = container.Resolve<Type3>(); Console.ReadKey(); } public class Type1 { } public class Type2 { } public class Type3 { private Type1 t; private Type2 t2; public Type3(Type1 t, Type2 t2) { this.t = t; this.t2 = t2; } } 

Update: I included a type with two parameters in the constructor, to show it can also be enabled.

+2
source share

I do not want to register an instance of Type2 in the source container. An instance of type2 may be different for different instances of Type1.

My next attempt is to create a child container and register a specific Type2 instance there.

0
source share

Try using named instances:

 IUnityContainer container = new UnityContainer(); container.RegisterType<Type1>(); container.RegisterType<Type2>("Instance 1", new ContainerControlledLifetimeManager()); container.RegisterType<Type2>("Instance 2", new ContainerControlledLifetimeManager()); container.RegisterType<Type3>(); Type1 type1 = container.Resolve<Type1>(); if (type1 == ...) { Type2 instance1 = container.Resolve<Type2>("Instance 1"); } else { Type2 instance2 = ontainer.Resolve<Type2>("Instance 2"); }
IUnityContainer container = new UnityContainer(); container.RegisterType<Type1>(); container.RegisterType<Type2>("Instance 1", new ContainerControlledLifetimeManager()); container.RegisterType<Type2>("Instance 2", new ContainerControlledLifetimeManager()); container.RegisterType<Type3>(); Type1 type1 = container.Resolve<Type1>(); if (type1 == ...) { Type2 instance1 = container.Resolve<Type2>("Instance 1"); } else { Type2 instance2 = ontainer.Resolve<Type2>("Instance 2"); } 

You can perform some type 1 checks and decide which type 2 instance you need. Note that the parameter "new ContainerControlledLifetimeManager ()" initializes an instance of a single type of the resistance type, so you always get the same instance of type 2.

Update: The same with interfaces. Hope this helps.

 IUnityContainer container = new UnityContainer(); container.RegisterType<TextDocument>(); container.RegisterType<ImageDocument>(); container.RegisterType(typeof (IView), typeof (TextView), "Text", new ContainerControlledLifetimeManager()); container.RegisterType(typeof (IView), typeof (ImageView), "Image", new ContainerControlledLifetimeManager()); IDocument document = container.Resolve<TextDocument>(); IView view = null; if (document is TextDocument) { view = container.Resolve<IView>("Text"); } else { view = container.Resolve<IView>("Image"); } view.Show();
IUnityContainer container = new UnityContainer(); container.RegisterType<TextDocument>(); container.RegisterType<ImageDocument>(); container.RegisterType(typeof (IView), typeof (TextView), "Text", new ContainerControlledLifetimeManager()); container.RegisterType(typeof (IView), typeof (ImageView), "Image", new ContainerControlledLifetimeManager()); IDocument document = container.Resolve<TextDocument>(); IView view = null; if (document is TextDocument) { view = container.Resolve<IView>("Text"); } else { view = container.Resolve<IView>("Image"); } view.Show(); 
0
source share

If you have a class with multiple constructors, you can decide which constructor is used by the Unity container using the "InjectionConstructor" attribute. This makes it possible to set some parameters manually.

 public class Test { public Test() { } // Always use the following constructor [InjectionConstructor] public Test(Type1 type1) : this() { } public Test(Type1 type1, Type2 type2) : this(type1) { } }
public class Test { public Test() { } // Always use the following constructor [InjectionConstructor] public Test(Type1 type1) : this() { } public Test(Type1 type1, Type2 type2) : this(type1) { } } 
0
source share

Use factory.

 public class Type1Factory { private Type3 type3; public Type1Factory(Type3 _type3) { type3 = _type3; } public GetType1(Type2 type2) { return new Type1(type2, type3); } } 

Call it like this:

 // SpellingChecker is subclass of Type3 IUnityContainer container = new UnityContainer(); container.RegisterType<Type3>(typeof(SpellingChecker)); // DocumentViewer is subclass of Type2 Type1Factory factory = container.Resolve<Type1Factory>(); Type1 type1 = factory.GetType1(new DocumentViewer()); 

It is assumed that you are trying to use Unity to resolve Type3 dependencies and that you have no control over the constructors in Type1. If you can edit Type1, use the Alexader R. clause so that Unity allows only one parameter constructor.

0
source share

You can use the container hierarchy, please read my answer on a similar question here: Microsoft Unity. How to specify a specific parameter in the constructor? .

The only difference is that you should use RegisterInstance() in your child container instead of RegisterType() . And maybe not, it depends on whether the instance was created earlier somewhere outside of your code or not.

0
source share

All Articles