6

I'm trying 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 the specific instance for Type2 to inject. This specific instance of Type2 is not registered in the container. Type3 is registered in the container and should be resolved as usual.

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

I want to be able to resolve DocumentViewer for a Document that is only known at runtime. Multiple DocumentViewer instances for differenct Documents can be created.

How can I do this?

Darko
  • 38,310
  • 15
  • 80
  • 107
  • Sorry i still don't get the point why it is not possible to resolve a instance of your document view with the code given in on of the answers below. What means "a Document is only known at runtime"? If you don't know the exact type of the document instance consider using interfaces. – Alexander Mar 06 '09 at 10:13
  • To say it in another way: I want to resolve a type, but only let the container resolve some of the dependencies itself. I want to provide the other instances myself. –  Mar 06 '09 at 10:35

5 Answers5

2

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

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 constructor to show it can also be resolved.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
REA_ANDREW
  • 10,666
  • 8
  • 48
  • 71
0

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

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

Community
  • 1
  • 1
Dmitrii Lobanov
  • 4,897
  • 1
  • 33
  • 50
0

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");
}


You can do some checks on type 1 and decide which instance of type 2 you will need. Note that the "new ContainerControlledLifetimeManager()" parameter will initialize a singleton instance of the resisted type, so you will always get the same instance of type 2.

Update: 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();

Alexander
  • 3,724
  • 8
  • 42
  • 50
0

If you have a class with multiple constructors, you can decide which constructor is used by the Unity container using the "InjectionConstructor" attribute. This gives you the possibility 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)
    {
    }
}

Alexander
  • 3,724
  • 8
  • 42
  • 50
0

Use a factory.

public class Type1Factory
{
  private Type3 type3;

  public Type1Factory(Type3 _type3)
  {
     type3 = _type3;
  }

  public GetType1(Type2 type2)
  {
    return new Type1(type2, type3);
  }
}

Call it this way:

// 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());

This assumes that you are only trying to use Unity to resolve the Type3 dependency, and that you have no control over the constructors in Type1. If you can edit Type1, use Alexader R.'s suggestion to make Unity only resolve the one parameter constructor.

Ray Henry
  • 905
  • 6
  • 12