Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating objects using Unity Resolve with extra parameters

I'm using Prism, which gives be the nice Unity IoC container too. I'm new to the concept, so I haven't gotten my hands all around it yet. What I want to do now is to create an object using the IoC container, but passing an extra parameter too. Allow me to explain with an example..:

I have a class that takes a commands object. This is registered in the IoC container, so it will handle it nicely:

public class Person 
{
    public Person(IApplicationCommands commands) { .. }
    ..
}

Person person = _container.Resolve<Person>();

Now - I want to pass in another argument - e.g. the name of the person. However, I still want to use the IoC container to handle the resolving and hence get the other paramenters from the IoC container. But pass in the name as a "custom" parameter. Can this be done?

public class Person 
{
    public Person(IApplicationCommands commands, string name) { .. }
    ..
}

string name = "John"; 
Person person = _container.Resolve<Person>(name); // ....?? 

This example doesn't seem to work, but is there a way to make it work? Or does Unity IoC container require all parameters to be registered in the container before calling Resolve?

like image 834
stiank81 Avatar asked Oct 02 '09 13:10

stiank81


People also ask

What is Injectionconstructor?

A class that holds the collection of information for a constructor, so that the container can be configured to call this constructor.

What is IUnityContainer?

The Unity Container (Unity) is a full featured, extensible dependency injection container. It facilitates building loosely coupled applications and provides developers with the following advantages: Simplified object creation, especially for hierarchical object structures and dependencies.

What is Unity dependency injection?

Dependency Injection (DI) Dependency Injection is defined as a design pattern that allows removing hard-coded dependencies from an application. There is one major point to remember: “Inversion of control is principal and Dependency Injection is implementation”.


3 Answers

Can I pass constructor parameters to Unity's Resolve() method?

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"
like image 110
NotDan Avatar answered Oct 21 '22 02:10

NotDan


Edit: this answer is obsolete, in my opinion, because it has an assumption of an older version of Unity. NotDan's answer is better.


You've got a few options. They are honestly a bit lame, but they will work.

Option 1: Scoped Container

If you want to use constructor injection, you'll need to create a scoped container and put your data into that scoped container:

IUnityContainer subContainer = _container.CreateChildContainer();

//Don't do this... create a custom type other than string, like
// MyConstructorParams or something like that... this gets the point across.
subContainer.RegisterInstance<string>("John");
Person person = subContainer.Resolve<Person>();

Option 2: Initialize Method

What I typically do, though, is have a seperate Initialize method on my target objects for instance variables:

public class Person
{
     public Person(IApplicationCommands commands)
     { .. }
     public void Initialize(string name) { .. }

     ..
}

And then your usage becomes:

Person person = container.Resolve<Person>();
person.Initialize("John");

Neither is particularly pleasant, but it'll get the job done. The important thing is to pick a convention and stick to it, otherwise you'll get a bit lost.

Hope this helps.

like image 42
Anderson Imes Avatar answered Oct 21 '22 03:10

Anderson Imes


There are a few choices you might consider:

In the case where you need to create a new entity which has legitimate dependencies in addition to any data being supplied (e.g. customer name), encapsulate this into a factory which itself has been injected into the calling object:

Person person = _personFactory.CreatePerson("bubba");

The factory can be injected with the entity's dependencies and supplied to the constructor if required or set by other means if optional:

var person = new Person("bubba", _domainService);

For transient-variable dependencies, such as a strategy used by a particular method, use Double Dispatch:

public class Person
{
    public void DoSomethingWith(SomeStrategy strategy)
    {
        strategy.DoSomething(this);
    }
 }

like image 4
Derek Greer Avatar answered Oct 21 '22 02:10

Derek Greer