2013-05-06 2 views
13

На данный момент я немного экспериментирую с контейнерами для инъекций зависимостей, на этот раз с Unity.Зависимость впрыска и другие параметры конструктора - плохая практика?

Учитывая следующий интерфейс:

public interface IPodcastCommService 
{ 
    void Download(); 

    void Upload(); 
} 

и последующее выполнение:

public class PodcastService 
{ 
    private IPodcastCommService commservice; 
    private String url; 

    public PodcastService(String url, IPodcastCommService commservice) 
    { 
     this.commservice = commservice; 
     this.url = url; 
    } 
} 

Из конструктора, я искал решение передать параметр к нему и нашел его:

var p = container.Resolve<IPodcastCommService>(new ParameterOverride("url", myUrl)); 

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

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

Update: Одним из примеров, где я читал, что это плохой дизайн, это:

Но могут быть случаи, когда вы должны пройти в пользовательских параметров конструктора для операции решимостью. Некоторые могут утверждать, что это крики плохой архитектуры, но есть ситуации, такие как приведение DI-контейнера в унаследованную систему, которая может потребовать такого рода действия.

Источник: http://mikaelkoskinen.net/unity-passing-constructor-parameters-to-resolve/

+1

не могли бы вы сказать мне, где у вас красный, что это плохой дизайн? Потому что я на самом деле думаю, что этот дизайн лучший, который вы когда-либо получите. – Egi

+0

@Egi: Я обновил свой вопрос с помощью источника. – Kai

+0

Вы можете использовать [ServiceLocator] (https://commonservicelocator.codeplex.com/) для выполнения DI без указания введенных свойств в конструкторе. – orad

ответ

3

Я не понимаю, почему вам нужен PodcastService с составом IPodcastCommService, вместо реализованного IPodcastCommService и имеет код, вводимый строкой. Я не понимаю, почему ваш дизайн плох. Инъекционный URL хорош ИМХО.

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

public class PodcastService 
{ 
    private IPodcastCommService commservice; 
    private IConnectionContext connection; 

    public PodcastService(IConnectionContext connection, IPodcastCommService commservice) 
    { 
     this.commservice = commservice; 
     this.connection= connection; 
    } 
} 

public interface IConnectionContext{ 
    string PodcastServiceUrl{get;} 
} 

Но опять же, я не нахожу никакой пользы от него (за исключением вы можете обрабатывать сессии/константы/статические поля) из обычного подхода.

UPDATE:

Я нашел похожий вопрос о плохом дизайне here. Таким образом, это не так, что параметр родного типа (строка и т. Д.) Или настраиваемый параметр конструктора плох. Просто вам нужно поставить параметр в класс, который действительно отвечает за параметр. И настраиваемый параметр конструктора потребуется, если вы обрабатываете условие if-else внутри абстрактного шаблона фабрики.

-3

Это зависит от структуры юй используют. Например, точка интеграции провайдеров asp.net mvc для контейнеров IoC, таких как DependecyResolver. Вы должны поместить всю свою логику для построения объектов и ввода зависимостей там. Если вы используете aps.net, у вас может быть какая-то базовая страница, из которой preinit eevnt вводит зависимости. Вы не можете использовать инсталляцию конструктора с asp.net, только вложение свойств. С winforms вы можете использовать какой-то тип фабрики для создания объектов формы.

1

В вашем сценарии я думаю, что DI через конструктор отлично работает. Причина, по которой это считается лучшим вариантом для перехода через свойства, заключается в том, что лучше читать, т. Е. Представить, как выглядел бы ваш конструктор, если вам нужно было ввести 20 свойств.

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

+2

Если есть несколько парочек инъекций, вы можете использовать шаблон 'Builder', чтобы упростить читаемость. Я думаю, что это намного лучше, чем использование свойств, если объект * требует * свойств, которые должны быть установлены до его использования. –

+2

, если у вашего конструктора 20 аргументов, я бы поспорил, что ваш класс вуалирует SRP и должен быть реорганизован на более мелкие классы, вместо того чтобы злоупотреблять инъекцией свойств для лучшей читаемости! инъекция свойств, на мой взгляд, хороша, если вам нужно динамическое поведение, которое должно быть в состоянии изменить во время выполнения. – Egi

1

Может

container.RegisterType<PodcastService>(new InjectionConstructor("myUrlParameter")); 

бы лучше, не так ли?

, но если вам нужно больше, чем один подкаст-сервис, и им нужен другой url, параметрoverride в порядке, я думаю.

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