2012-04-23 2 views
1

У меня странная проблема с единством метода BuildUp. У меня есть один интерфейс, который сопоставляется с тремя классами. Я дал имя каждому отображению.Метод BuildUp в единстве не учитывает MappingName

Теперь мне нужно ввести зависимость в существующий объект (это атрибут, поэтому я не имею контроля над временем жизни). Я вызываю метод BuildUp для инъекции зависимости, но он всегда генерирует исключение, которое говорит о том, что интерфейс не отображается.

Если я сопоставляю интерфейс только с одним типом, и я удаляю имя сопоставления, работает метод BuildUp. Если я сопоставляю интерфейс только с одним типом, и я указываю имя сопоставления, метод BuildUp терпит неудачу. Я пробовал регистрировать типы в конфигурации и коде, и ничего не меняется.

Я подозреваю, что это ошибка, но я хотел бы знать, есть ли у кого-нибудь другая идея.

Это, как я называю метод нароста:

var newAttr = _container.BuildUp(myAttribute.GetType(), myAttribute, "Mapping1"); 
+0

Попробуйте указать тип интерфейса вместо конкретных реализаций. Тип для метода «BuildUp» –

+0

Спасибо, Себастьян, но это не главное. Если я зарегистрирую один интерфейс с одним типом, метод _container.BuildUp (myAttribute.GetType(), myAttribute) работает без проблем. Проблема возникает только при использовании имени сопоставления. – user1350775

ответ

1

Я пытался следовать своему сценарию, и этот пример работает

var container = new UnityContainer(); 
container.RegisterType<IFoo, One>("1", new InjectionProperty("Bar", "1")); 
container.RegisterType<IFoo, Two>("2", new InjectionProperty("Bar", "2")); 
container.RegisterType<IFoo, Three>("3", new InjectionProperty("Bar", "3")); 
One one = new One(); 
container.BuildUp(one.GetType(), one, "1"); 
Assert.AreEqual("1", one.Bar); 

public interface IFoo 
{ 
    string Bar { get; set; } 
} 
public class One : IFoo 
{ 
    public string Bar { get; set; } 
} 
public class Two : IFoo 
{ 
    public string Bar { get; set; } 
} 
public class Three : IFoo 
{ 
    public string Bar { get; set; } 
} 

Update

var container = new UnityContainer(); 
container.RegisterType<Person>(new InjectionProperty("Foo")); 
container.RegisterType<IFoo, One>("1"); 
container.RegisterType<IFoo, Two>("2"); 
container.RegisterType<IFoo, Three>("3"); 
Person person = container.Resolve<Person>("1"); 
Assert.IsNotNull(person.Foo); 
Assert.IsInstanceOfType(person.Foo, typeof(One)); 

public class Person 
{ 
    public IFoo Foo { get; set; } 
} 

Я думаю, это то, что вы имеете в виду? Короткий ответ: Это не так, как работает Unity.

Длинный ответ: вам нужно указать ResolverOverride, который сделает это за вас. Но даже этого недостаточно, так как вы хотите, чтобы контейнер создавал значение, которое вы хотите ввести для вас. Поэтому вам нужно указать ResolvedParameter в качестве значения для вашего ResolverOverride. С вышедших из коробки частей Единству Resolve будет выглядеть следующим образом

Person person = container.Resolve<Person>(new PropertyOverride("Foo", new ResolvedParameter(typeof(IFoo), "1"))); 

Или вы можете использовать этот обычай переопределение вместо

public class NamedPropertyOverride : ResolverOverride 
{ 
    private readonly string propertyName; 
    private readonly string registrationName; 
    public NamedPropertyOverride(string propertyName, string registrationName) 
    { 
    this.propertyName = propertyName; 
    this.registrationName = registrationName; 
    } 
    public override IDependencyResolverPolicy GetResolver(IBuilderContext context, Type dependencyType) 
    { 
    var currentOperation = context.CurrentOperation as ResolvingPropertyValueOperation; 
    if (currentOperation != null && 
     currentOperation.PropertyName == this.propertyName) 
    { 
     Type propertyType = currentOperation 
     .TypeBeingConstructed 
     .GetProperty(currentOperation.PropertyName, BindingFlags.Instance | BindingFlags.Public) 
     .PropertyType; 
     return new NamedTypeDependencyResolverPolicy(propertyType, this.registrationName); 
    } 
    return null; 
    } 
} 

Измените строку, которая содержит призыв к Resolve в вышеуказанном образец к этому

Person person = container.Resolve<Person>(new NamedPropertyOverride("Foo", "1")); 

Это должно сделать трюк.

+0

Спасибо, Себастьян, но моя ситуация немного отличается. У меня есть экземпляр Person, у которого есть свойство Foo типа IFoo. Вне класса person я должен ввести экземпляр класса, который реализует IFoo в свойстве Foo. – user1350775

+0

@ user1350775 Не могли бы вы показать код, который описывает вашу проблему. –

+0

@ user1350775 См. Мое обновление –

Смежные вопросы