именованный тип не используется для внедрения в конструктор - PullRequest
5 голосов
/ 05 мая 2010

У меня есть простое консольное приложение, в котором у меня есть следующие настройки:

public interface ILogger
{
   void Log(string message);
}

class NullLogger : ILogger
{
   private readonly string version;

   public NullLogger()
   {
      version = "1.0";
   }
   public NullLogger(string v)
   {
      version = v;
   }
   public void Log(string message)
   {
     Console.WriteLine("NULL> " + version + " : " + message);
   }
}

Подробности конфигурации приведены ниже:

<type type="UnityConsole.ILogger, UnityConsole" mapTo="UnityConsole.NullLogger, UnityConsole">
 <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
   <constructor>
     <param name="message" parameterType="System.String" >
        <value value="2.0" type="System.String"/>
     </param>
   </constructor>
 </typeConfig>

Мой код вызова выглядит следующим образом:

IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
ILogger nullLogger = container.Resolve<ILogger>();
nullLogger.Log("hello");

Это прекрасно работает, но как только я даю имя этому типу, что-то вроде:

<type type="UnityConsole.ILogger, UnityConsole" mapTo="UnityConsole.NullLogger, UnityConsole" name="NullLogger">
 <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
   <constructor>
     <param name="message" parameterType="System.String" >
       <value value="2.0" type="System.String"/>
     </param>
   </constructor>
 </typeConfig>

Вышеуказанный код вызова не работает, даже если я явно зарегистрировал тип, используя

container.RegisterType<ILogger, NullLogger>();

Я получаю ошибку:

{"Не удалось разрешить зависимость, type = \" UnityConsole.ILogger \ ", name = \" \ ". Сообщение об исключении: текущая операция сборки (ключ сборки [Создать ключ [UnityConsole.NullLogger, ноль]) : Параметр v не может быть разрешен при попытке вызвать конструктор UnityConsole.NullLogger (System.String v). (Тип стратегии BuildPlanStrategy, index 3) "}

Почему единство не смотрит на именованные экземпляры? Чтобы заставить его работать, мне нужно сделать:

ILogger nullLogger = container.Resolve<ILogger>("NullLogger");

Где это поведение задокументировано?

Arun

1 Ответ

5 голосов
/ 05 мая 2010

Как вы знаете - существует два типа экземпляров: именованные (может быть много) и по умолчанию (может быть только один, и у них нет имен)

Resolve () - не просматривает именованные экземпляры - он ищет только значения по умолчанию и, если экземпляр по умолчанию отсутствует

  • возвращает экземпляр T, если это возможно построено или
  • исключение, если не может
    • в случае интерфейсов
    • или когда класс не имеет конструктора,
    • или единица не может разрешить параметр для конструктор этого типа

Итак, давайте посмотрим на ваш пример. Первый простой вопрос - почему код перестал работать, когда вы указали имя в конфигурации. Ответ заключается в том, что теперь для ILogger нет зарегистрированного экземпляра по умолчанию, и Resolve () - не просматривает именованные экземпляры - он ищет только значения по умолчанию.

Второй вопрос Почему не работает после container.RegisterType<ILogger, NullLogger>(); Ответ заключается в том, что единство является жадным, когда он выбирает конструкторы для типа. Вообще говоря, он всегда принимает конструктор, где количество параметров больше. Так что public NullLogger(string v) не удалось создать строку (вы можете увидеть это во внутреннем исключении). Нет информации о том, какой конструктор выбрать для разрешения по умолчанию. Вся информация о названных. И именно поэтому

ILogger nullLogger = container.Resolve<ILogger>("NullLogger");

работает.

Это поведение, задокументированное в справке, которое можно скачать здесь http://unity.codeplex.com/releases/view/18855. Или вы можете посмотреть здесь http://msdn.microsoft.com/en-us/library/ff649334.aspx

...