2015-06-10 2 views
0

Я проектирую класс, который использует абстрактное свойство, чтобы предоставить точку доступа к полю. Вот отрывок из моего кода:Когда использовать DI над абстрактным наследованием?

public abstract class PageBroker : WebBroker 
{ 
    public abstract IPageProvider Provider { get; } 
} 

public class ArticleBroker : PageBroker 
{ 
    public override IPageProvider Provider { get; } = new ArticleProvider(); 
} 

я понял, что я мог бы реорганизовать это использовать DI вместо этого, например, так:

public class PageBroker : WebBroker 
{ 
    public PageBroker(IPageProvider provider) 
    { 
     this.Provider = provider; 
    } 

    public IPageProvider Provider { get; private set; } 

    // implementation... 
} 

// no derived class, just new PageBroker(new ArticleProvider()) 

В какой ситуации (ы) будет один метод целесообразно над другим ?

+1

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

+1

@DStanley Извините, это был не мой вопрос. Я спрашивал, должен ли я сделать ** свойство «abstract», поэтому производный класс может реализовать его ** или передать его через конструктор. Это не имеет никакого отношения к инъекции сеттера. –

+0

Ну, конструкторы не наследуются, поэтому производному классу придется «переопределить» что-то в любом случае. Поэтому я не уверен, какую разницу вы ищете (за исключением установки и инсталляции конструктора). –

ответ

3

Я согласен с ответом BJ Safdie в..

Сказанное, я думаю, что основное отличие заключается в том, что в первой реализации ArticleBroker связан с конкретной реализацией IPageProvider (а именно ArticleProvider). Если это предназначено, я не вижу проблем с этим. Однако, если вы хотите обеспечить реализацию IPageProvider во время выполнения (либо в производственном коде, либо в модульном тесте через mocks/fakes), то инъекция зависимости - лучший выбор.

2

Речь идет о преимуществе композиции над наследованием, что является хорошим ориентиром. Я бы предположил, что, поскольку у PageBroker есть IPageProvider, вы должны использовать DI. Пользователи класса могут предоставлять альтернативные реализации без наследования, скажем, чтобы ввести тестовый IPageProvider. По этой причине я бы пошел с ДИ.

Если есть экзистенциальная разница на основе IPageProvider таким образом, что с помощью другого поставщика семантический необходимо отразить является отношения (подтип PageBroker), то я бы с абстрактным классом.

1

Как уже говорилось, я бы заполнил ваш провайдер DI. Это говорит, что вы хотите получить через абстрактный класс? Если это просто для ввода IPageProvider, то больше нечего сказать.

Если, однако, у вас есть другие общие методы, которые очень специфичны для WebBrokers или PageBrokers, то почему бы не использовать их оба?

Например:

public abstract class WebBroker 
{ 
    private IPageProvider _pageProvider; 

    protected WebBroker(IPageProvider pageProvider) 
    { 
     _pageProvider = pageProvider; 
    } 

    public override void CommonThing(int someData) 
    { 
     var result = _pageProvider.CommonMethod(someData); 
     //do something with result 
    } 
} 

Теперь все ваши WebBrokers есть метод CommonThing который использует _pageProvider, что DI передается в

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