Статьи

NanoIoC: простое внедрение зависимостей на Windows Phone

Что касается внедрения зависимостей / IOC, то для Windows Phone не очень хорошая история
[1] .

Там нет ничего встроенного, и многие люди создали свои собственные решения. Включая, но не ограничиваясь:
Funq ,
MicroIoc ,
TinyIoc ,
это или
это . Но никто из них не работает так, как я хочу.

Я хочу:

  • Автоматическое введение параметров конструктора
  • Явное указание того, где существует зависимость
  • Явная конфигурация того, как должны быть разрешены зависимости
  • Свободная конфигурация

Я не хочу

  • Параметр впрыска
  • Автоматическое разрешение зависимостей
  • Aribtrary ServiceLocator

Меня не волнует

  • Позволяя контейнеру управлять синглетонами
  • Вложенное / связанное разрешение зависимостей

На мои требования влияют два фактора:

1. Мой предыдущий опыт работы с
Castle Windsor — выбран после оценки того, что было доступно в то время (около 4 лет назад).

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

Итак, я написал что-то сам:
http://github.com/mrlacey/NanoIoC


Как отмечено в комментариях, это не обеспечивает автоматическое внедрение конструктора.
К сожалению, платформа просто не поддерживает способ сделать это. Это моя следующая лучшая вещь. — Надеюсь, это прояснит ситуацию.

Да, название — это ссылка на MicroIoc & TinyIoC, но намекает, что у меня
гораздо меньше кода. (Это меньше 90 LOC.)

Да, я знаю, что это скорее структура DI, чем IOC, но в реальном мире термины используются довольно взаимозаменяемо, поэтому я доволен этим.

Как это использовать:

Для класса, который имеет некоторые внешние зависимости, мы объявляем это, помечая их интерфейсом «ISupportInjectionOf <T>». В качестве примера, если бы мы хотели указать, что страница имеет зависимость до «IRepository» и «IDateTimeHelper», мы бы сделали это:

public partial class MainPage : PhoneApplicationPage,
                                ISupportInjectionOf<IRepository>,
                                ISupportInjectionOf<IDateTimeHelper>
{

Затем в нашем конструкторе мы разрешим эти зависимости:

private IRepository repository;
 
private IDateTimeHelper dateTime;
 
public MainPage()
{
    InitializeComponent();
 
    repository = this.GetDependency<IRepository>();
    dateTime = this.GetDependency<IDateTimeHelper>();
}

Да, мы можем разрешить зависимости в любое время, но в моем коде это всегда будет в конструкторах.

Это важно для поддержания тестируемости и ремонтопригодности. (Я устанавливаю соглашение.)

В приведенном выше примере я бы также включил перегрузку конструктора для непосредственного внедрения зависимостей во время тестирования:

#if TEST
        public MainPage(IRepository repo, IDateTimeHelper dateTimeHelper)
        {
            InitializeComponent();
 
            this.repository = repo;
            this.dateTime = dateTimeHelper;
        }
#endif

Просто!

Конфигурация:

Конфигурация проста и выполняется на уровне приложения. Мы можем объявить, как каждая зависимость должна решаться отдельно:

NanoIocConfig.RegisterDependency<IRepository>(new ViewModelRepository());
NanoIocConfig.RegisterDependency<IDateTimeHelper>(new DateTimeHelper());

Или через свободный интерфейс:

NanoIocConfig.RegisterDependency<IRepository>(new ViewModelRepository())
             .And<IDateTimeHelper>(new DateTimeHelper());

Очевидно, что все эти примеры используют интерфейсы. Но мы не должны. Предполагая, что мы не хотим скрывать «DateTimeHelper» за интерфейсом, мы можем просто сделать это (обратите внимание, что тип выводится):

NanoIocConfig.RegisterDependency(new DateTimeHelper());
 
dth = this.GetDependency<DateTimeHelper>();

Все приведенные выше примеры создают экземпляр для использования каждый раз, когда зависимость разрешается.

Вместо этого мы могли бы передать экземпляр синглтона традиционным способом:

NanoIocConfig.RegisterDependency<IRepository>(ViewModelRepository.Instance);

Если вам нужны разные экземпляры каждый раз, когда зависимость разрешается, просто передайте фабрику и получите новые экземпляры таким образом.

Что вы думаете?

Полезно?

Интересный?

Что-то, что вы можете использовать?

Хотите, чтобы он был включен в пакет NuGet? (Либо в виде библиотеки, либо в виде одного исходного файла).

Мне бы очень хотелось узнать, что вы думаете.

[1] Было бы замечательно, если бы в (предпочтительно близкой) будущей версии Windows Phone SDK он включал инструменты, которые позволят упростить реализацию хороших методов разработки в нашем коде Windows Phone. Удивительно, что они упростили людям начало разработки для платформы, но эти новички должны со временем знать, как написать лучший код, и если инструменты их остановят, у них нет стимула учиться. А для тех из нас, кто считает себя профессионалами и зарабатывает на жизнь, мы хотим иметь возможность применять лучшие практики к нашему коду (работе), а не иметь SDK и инструментарий, мешающих нам делать основные вещи.

Вернуться к началу