Creating objects using Unity Resolve with extra parameters

谁说我不能喝 提交于 2019-12-21 07:24:16

问题


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?


回答1:


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.




回答2:


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

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"



回答3:


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




回答4:


I can't think of any way to do this with constructor injection. I think you'll need to use property injection for the dependencies (marked with the Dependency attribute) and then either take just the string in the constructor, instantiate yourself, then use BuildUp to wire the dependencies, or make the string a property too that you set manually after Resolve.



来源:https://stackoverflow.com/questions/1509438/creating-objects-using-unity-resolve-with-extra-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!