Параметризация объекта с помощью enum - PullRequest
4 голосов
/ 14 мая 2011

Я использую C # и Unity Dependency Injection для разработки приложения MVVM в WPF.Я ищу чистое решение для следующей проблемы.

Некоторые из моих классов параметризованы с помощью перечислений, например, у меня есть класс AudioChannelViewModel (давайте назовем его для краткости A), и я хочу зарегистрировать дваэкземпляры класса, один для Channel.Left и один для Channel.Right.Это само по себе не является проблемой, потому что я регистрирую эти экземпляры, называя их в RegisterType и затем ссылаясь на них позже с помощью атрибута [Dependency(name)].

Кроме того, A зависит от некоторых других классов, давайте называть их Dep1, Dep2и Dep3.Чтобы выполнить инициализацию A, я должен иметь ВСЕ свои зависимости и информацию о канале.

Я пытался использовать следующие стратегии:

  1. Внедрение свойстваDep1, Dep2 и Dep3 и установка канала A в конструкторе с помощью RegisterType с параметром InjectionConstructor.Но как мне узнать, когда A готов к инициализации?AFAIK Я ничего не могу предположить о порядке внедрения свойств.

  2. Внедрение в конструктор всех четырех элементов.Это было бы ИМХО самое чистое решение, так как я мог бы выполнить инициализацию в конструкторе.Но я не могу заставить это работать в Unity.Регистрация A с параметром InjectionConstructor для Channel вызывает исключение, а регистрация с четырьмя параметрами InjectionConstructor кажется уродливой.

  3. Внедрение в конструкторы Dep1, Dep2 и Dep3 и внедрение свойства Channel.Затем я могу инициализировать свой класс в установщике каналов.Это работает для этого случая, но что если A будет параметризован более чем одним свойством?Тогда я бы не знал, когда А будет полностью собран и готов к инициализации.

Как должна выполняться инициализация?Или, может быть, я делаю вещи слишком сложными.

1 Ответ

4 голосов
/ 15 мая 2011

Вы не говорите точно, что именно за исключением того, что вы наблюдали в стратегии # 2, но я бы использовал этот подход (учитывая ваши другие требования для возможности другой инициализации после успешного разрешения всех зависимостей). Я подозреваю, что проблема в том, что вы не предоставляете «значение» для всех аргументов конструктора ... InjectionConstructor предполагает, что вы хотите, чтобы конструктор соответствовал типам значений, предоставленных InjectionConstructor.

например. если вы хотите зарегистрировать конструктор для такого класса ...

public class AudioChannelViewModel {
  public AudioChannelViewModel(Channel channel, Dep1 dep1, Dep2 dep2, Dep3 dep3) {
    ...
  }
}

Вы должны зарегистрировать его таким образом ...

container.RegisterType<AudioChannelViewModel>("left", 
    new InjectionConstructor(Channel.Left,
      typeof(Dep1), typeof(Dep2), typeof(Dep3)));
container.RegisterType<AudioChannelViewModel>("right", 
    new InjectionConstructor(Channel.Right,
      typeof(Dep1), typeof(Dep2), typeof(Dep3)));

Unity будет использовать предоставленное значение для первого аргумента (значение перечисления Channel) и затем разрешит экземпляры Dep1, Dep2 и Dep3. Вы также можете использовать ResolvedParameter<T> в качестве аргумента для InjectionConstructor, если вам нужны конкретные именованные экземпляры Dep1, Dep2 или Dep3, которые вам требуются.

Недостаточно просто указать Channel.Left или Channel.Right, поскольку Unity будет считать, что его просят использовать конструктор с аргументом Channel.

Или; если вы уже пробовали это, и это не работает ... возможно, Unity не поддерживает перечисления в этом случае (каламбур предназначен).

Эта страница MSDN может пролить дополнительный свет на проблему.

...