Какви са основните принципи на проектиране по шаблон за инжектиране на зависимости

Нов съм в идеята за изцяло DI модел и имам някои основни съмнения относно дизайна. използвам блокове на приложение Unity 2.0 като моя DI рамка.

На въпросите:

  1. Да кажем, че имам интерфейс за HW устройства, наречен IDevice. И някакъв HW слушател, който получава такова IDevice. Сега кажете, че имате няколко HW устройства, които имплементират IDevice и няколко слушателя. Трябва да посочите за всеки слушател кое действително устройство да се инжектира. Не можете просто да картографирате едно устройство към интерфейса, имате нужда от нещо като множествено картографиране.

едно възможно решение е да се създаде друго ниво на абстракция за всяко действително устройство като

public interface IActualDevice : IDevice
{}

public ActualDevice : IActualDevice
{}

public SimulatedActualDevice : IActualDevice
{}

public OtherAcualDevice: IOtherAcualDevice
{}

тогава би било възможно да се създаде такъв вид картографиране:

container.RegisterType<IActualDevice, ActualDevice>()

или ако HW липсва:

container.RegisterType<IActualDevice, SimulatedActualDevice>()

така че какво ще кажете дали този дизайн е добър?

  1. DI моделът ни дава добрия механизъм за създаване на обекти.

Какво ще кажете за лепилото, какво ще кажете за абонамента за събития между обекти?

не мислите ли, че липсва или по-добре липсва ми някаква функция на Unity, която го поддържа.

Адиел.


person Adiel Yaacov    schedule 15.07.2010    source източник


Отговори (2)


Няма нужда да въвеждате маркерни интерфейси, за да работи вашият DI контейнер - това би било Пропусклива абстракция.

С Unity можете да конфигурирате всеки слушател със собствена реализация на IDevice по следния начин:

container.RegisterType<IDevice, ActualDevice>("actual");
container.RegisterType<IDevice, OtherActualDevice>("otherActual");

container.RegisterType<IListener, Listener1>("listener1",
    new InjectionConstructor(
        new ResolvedParameter<IDevice>("actual")));
container.RegisterType<IListener, Listener2>("listener2",
    new InjectionConstructor(
        new ResolvedParameter<IDevice>("otherActual")));

Вече можете да разрешите слушателите по следния начин:

var listener1 = container.Resolve<IListener>("listener1");
var listener2 = container.Resolve<IListener>("listener2");

Като цяло, основните модели на DI са Инжектиране на конструктор и Абстрактна фабрика. Повечето други неща следват от тези двете. Вижте този отговор за повече DI модели и принципи.

person Mark Seemann    schedule 15.07.2010
comment
точно отговора, който търсех на първия въпрос. Предложих абстракцията Leaky, макар да знаех, че е грозна, само за да разбера, за да изясня мнението си. Що се отнася до втория ми въпрос, мисля да имам AppFactory, който ще накара да произвежда Glue - целия абонамент за събития между събитията. какво казваш ? - person Adiel Yaacov; 15.07.2010
comment
Може да искате да разгледате събитията на домейни: msdn.microsoft.com/en-us /magazine/ee236415.aspx - person Mark Seemann; 15.07.2010

1) Това е напълно лоша идея, защото интерфейсите са предназначени да скрият подробности за изпълнението. Използвайте тип IDevice навсякъде и инжектирайте тази зависимост ръчно

IDevice d;

if(a == 1)
{
   d = container.Resolve<SimulatedActualDevice>()
}
else
{
   d = container.Resolve<ActualDevice>()
}

User user = container.Resolve<IUser>();
user.Device = d;

Ако не искате да използвате имена на класове за изпълнение в кода, тогава използвайте наименувани регистрации:

IDevice d;

if(a == 1)
{
   d = container.Resolve<IDevice>("Simulated")
}
else
{
   d = container.Resolve<IDevice>("Actual")
}

User user = container.Resolve<IUser>();
user.Device = d;

2) Абонаментът за събития между обекти е част от инициализацията на обекта, но не и част от създаването. Unity просто капсулира "новите" оператори. Правете абонаменти в конструктори или в специални фабрики, както правехте преди да използвате DI контейнер.

person Yauheni Sivukha    schedule 15.07.2010
comment
-1 Този отговор препоръчва и Тясно свързване, и Антимодел на локатора на услуги – и двете изключително лоши идеи. - person Mark Seemann; 15.07.2010
comment
Tight Coupling се използва само като пример и всъщност това не е толкова лоша идея със стратегически модел. Що се отнася до локатора на услуги - моля, предложете друг начин. Най-честият пример - Как динамично да създаваме обекти с различни стратегии? - person Yauheni Sivukha; 15.07.2010
comment
Да, и как ще реализирате такава абстрактна фабрика? Създайте ръчно обект като в stackoverflow.com/questions/1926826 /cant-combine-factory-di/? В този случай вашата абстрактна фабрика ще има куп ненужни зависимости. Много по-добре е да използвате Tight Coupling и Service Locator, докато внедрявате тази фабрика. - person Yauheni Sivukha; 15.07.2010
comment
Вижте коментара ми по този въпрос. - person Mark Seemann; 15.07.2010