Создание объектов с использованием Unity Resolve с дополнительными параметрами
Я использую Prism, который также является хорошим контейнером Unity IoC. Я новичок в этой концепции, поэтому я еще не обнял ее. Теперь я хочу создать объект с помощью контейнера IoC, но также передать дополнительный параметр. Позвольте мне объяснить на примере..:
У меня есть класс, который принимает объект команд. Это зарегистрировано в контейнере IoC, поэтому он будет обрабатывать его красиво:
public class Person
{
public Person(IApplicationCommands commands) { .. }
..
}
Person person = _container.Resolve<Person>();
Теперь - я хочу передать другой аргумент - например. имя человека. Тем не менее, я все еще хочу использовать контейнер IoC для обработки разрешающей способности и, следовательно, получить другие параадресы из контейнера IoC. Но передайте имя как "пользовательский" параметр. Это можно сделать?
public class Person
{
public Person(IApplicationCommands commands, string name) { .. }
..
}
string name = "John";
Person person = _container.Resolve<Person>(name); // ....??
Этот пример, похоже, не работает, но есть ли способ заставить его работать? Или контейнер Unity IoC требует, чтобы все параметры регистрировались в контейнере до вызова Resolve?
Ответы
Ответ 1
Изменить: этот ответ устарел, на мой взгляд, потому что он имеет предположение о более старой версии Unity. Ответ NotDan лучше.
У вас есть несколько вариантов. Они честно немного хромают, но они будут работать.
Вариант 1: Контейнер с областью
Если вы хотите использовать конструктор инъекции, вам необходимо создать и скопируйте ваши данные в этот контейнер с областью:
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>();
Вариант 2: Инициализировать метод
То, что я обычно делаю, однако, имеет отдельный метод инициализации на моем целевые объекты для переменных экземпляра:
public class Person
{
public Person(IApplicationCommands commands)
{ .. }
public void Initialize(string name) { .. }
..
}
И тогда ваше использование будет:
Person person = container.Resolve<Person>();
person.Initialize("John");
Ничего особенного, но он выполнит свою работу. Важно выбрать конвенцию и придерживаться ее, иначе вы немного потеряете.
Надеюсь, что это поможет.
Ответ 2
Могу ли я передать параметры конструктора методу Unity's Resolve()?
container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"
Ответ 3
Есть несколько вариантов, которые вы могли бы рассмотреть:
В случае, когда вам нужно создать новый объект с законными зависимостями в дополнение к любым предоставленным данным (например, имя клиента), инкапсулируйте его в factory, который сам был введен в вызывающий объект:
Person person = _personFactory.CreatePerson("bubba");
factory может быть введены зависимостями сущностей и предоставлен в конструктор, если требуется, или с помощью других средств, если это необязательно:
var person = new Person("bubba", _domainService);
Для зависимостей переходных переменных, таких как стратегия, используемая конкретным методом, используйте Double Dispatch:
public class Person
{
public void DoSomethingWith(SomeStrategy strategy)
{
strategy.DoSomething(this);
}
}
Ответ 4
Я не могу придумать никакого способа сделать это с помощью инъекции конструктора. Я думаю, вам нужно будет использовать вложение свойств для зависимостей (помеченных атрибутом Dependency), а затем либо взять только строку в конструкторе, создайте экземпляр самостоятельно, затем используйте BuildUp для подключения зависимостей или сделайте строку тоже свойством, которое вы установите вручную после Resolve.