Укажите конструктор для используемого контейнера Unity IoC - PullRequest
41 голосов
/ 29 января 2010

Я использую контейнер Unity IoC для разрешения своих объектов. Однако я столкнулся с проблемой. Когда у меня есть более одного конструктора - как Unity узнает, какой из них использовать? Кажется, использовать один с параметрами, когда у меня есть один с и без. Могу ли я явно сказать, какой конструктор использовать?

В частности, у меня был случай, похожий на следующий класс Person с двумя конструкторами. В этом случае я хочу, чтобы контейнер IoC использовал конструктор по умолчанию - без параметров - но он выбирает тот, у которого есть параметры.

public class SomeValueObject
{
    public SomeValueObject(string name)
    {
        Name = name; 
    }
    public string Name { get; set; }
}

public class Person
{
    private string _name; 

    public Person()
    {
        _name = string.Empty;
    }

    public Person(SomeValueObject obj)
    {
        _name = obj.Name;
    }
}

Это, очевидно, дает сбой, так как он не может создать SomeValueObject - не зная, что вставить в его строковый параметр. Ошибка, которую он дает:

Не удалось разрешить зависимость, type = "MyApp.Person", name = "". Сообщение об исключении: текущая операция сборки (ключ сборки [Build Key [MyApp.Person, null])) завершилась неудачно: не удалось разрешить параметр obj при попытке вызвать конструктор MyApp.Person (MyApp.SomeValueObject obj) (Тип стратегии BuildPlanStrategy, индекс 3)

Контейнерная регистрация:

Container.RegisterType<Person, Person>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());

И разрешение:

var person = Container.Resolve<Person>();

Ответы [ 4 ]

49 голосов
/ 29 января 2010

Зарегистрируйте это так вместо этого:

container.RegisterType<Person>(new InjectionConstructor());

Вы также можете добавить LifetimeManager, используя перегрузку метода RegisterType.

Тем не менее, при моделировании для DI ваша жизнь будет намного проще, если у вас есть однозначные конструкторы (то есть нет перегруженных конструкторов).

27 голосов
/ 29 января 2010

По умолчанию Unity выбирает конструктор с максимальным количеством аргументов. Чтобы переопределить это, украсьте необходимый конструктор с помощью InjectionConstructorAttribute .

4 голосов
/ 29 января 2010

Инъекция в несколько конструкторов с использованием атрибута

Когда целевой класс содержит более один конструктор с тем же номером параметров, вы должны применить Атрибут InjectionConstructor для конструктор, контейнер Unity будет использовать, чтобы указать, какой конструктор контейнер должен использовать. Как с автоматический конструктор инъекций, вы можно указать параметры конструктора как конкретный тип, или вы можете указать интерфейс или базовый класс, для которого контейнер Unity содержит зарегистрированное отображение.

0 голосов
/ 29 января 2010

Я действительно должен указать, что вы используете внедрение зависимостей в этом случае просто неправильно. Контейнер должен быть в состоянии внедрить SomeValueObject в конструкцию.

Скорее всего, вам нужно зарегистрировать объект по умолчанию SomeValueObject, который вместо свойства .Name возвращает string.Empty.

...