2011-01-17 5 views
6

Я вижу странное поведение в контейнере Unity при работе с двумя интерфейсами, которые оба регистрируются на одном и том же декораторе. Пример кода будет более понятным.Unity: Регистрация одного и того же типа для двух интерфейсов

у меня есть следующие иерархии классов:

public interface IBaseInterface 
    { 

    } 

    public interface IInterface1: IBaseInterface 
    { 

    } 
    public interface IInterface2: IBaseInterface 
    { 

    } 
    public class Interface1Impl : IInterface1 
    { 
    } 
    public class Interface2Impl : IInterface2 
    { 
    } 

    public class BaseInterfaceDecorator: IInterface1,IInterface2 
    { 
     private readonly IBaseInterface baseInterface; 

     public BaseInterfaceDecorator(IBaseInterface baseInterface) 
     { 
      this.baseInterface = baseInterface; 
     } 
    } 

    public class MyClass 
    { 
     private readonly IInterface1 interface1; 

     public MyClass(IInterface1 interface1) 
     { 
      this.interface1 = interface1; 
     }    
    } 

И это регистрационный код:

var container = new UnityContainer();   
     container.RegisterType<IInterface1, BaseInterfaceDecorator>(
      new InjectionConstructor(
       new ResolvedParameter<Interface1Impl>())); 

     container.RegisterType<IInterface2, BaseInterfaceDecorator>(
      new InjectionConstructor(
       new ResolvedParameter<Interface2Impl>())); 


     var dependency = container.Resolve<MyClass>(); 

При решении MyClass я получаю BaseInterfaceDecorator с Interface2Impl вместо Interface1Impl. Кажется странным для меня. Вы можете объяснить?

ответ

9

Похоже, что последняя инструкция по впрыску для заданных «на» типов выигрывает. Если вы возьмете копию Reflector и взгляните на реализацию UnityContainer.RegisterType (Type, Type, string, LifetimeManager, InjectionMember []), вы поймете, почему.

IMO, это поведение является ошибкой. По крайней мере, InjectedMembers.ConfigureInjectionFor (Type, string, InjectionMember []) должен генерировать исключение вместо молчащей замены предыдущей конфигурации впрыска. Тем не менее, это действительно должно поддержать то, что вы пытаетесь.

+0

В случае, если это не понятно для читателей; Internal Unity кэширует ключ сборки типа «to» (например, «TTo» в общих подписях.) В следующий раз, когда вы разрешите любой тип «TFrom», Build Build для «TTo» используется для выполнения сборки. Этот ключ сборки также связан с менеджером по продолжительности жизни, и, таким образом, Unity, как представляется, использует первый использованный менеджер времени жизни (в Build Up) для всех подсекторных разрешений для TTo (независимо от личности TFrom.) Это ошибка с Unity's Строить ключи. Обходной путь заключается в использовании именных регистраций, которые побеждают точку в определении идентичности ковариантного типа. –

2

Я не знаю, поможет ли это. Скорее всего, для вас это уже слишком поздно. Но это возможно, если вы используете именованную регистрацию, т. Е. Вы регистрируете каждый тип, который должен быть разрешен с другим именем.

Например:

Container.RegisterType<IInterface1, BaseInterfaceDecorator>("interface1"); 
Container.RegisterType<IInterface2, BaseInterfaceDecorator>("interface2"); 
+0

Это допустимое обходное решение, но оно побеждает цель использования ковариантных типов при регистрации. Unity делает предположение, что все решения для «TTo» относятся к той же конфигурации/инструкциям для создания экземпляра TTo. Таким образом, вы увидите проблемы с параметрами инъекций и управлением жизненным циклом, в которых идентификация TFrom должна приводить к различному поведению (разные парфюмы для инъекций, другой менеджер времени жизни и т. Д.), –

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