2016-11-07 7 views
2

У меня проблема с использованием DI со свойствами конструктора. Я строю PDFBuilder на основе моего IPDFBuilder.DI с использованием динамического впрыска конструктора

public interface IPDFBuilder 
{ 
    string templatefilepath { get; } 
    string templatefilename { get; } 
    Dictionary<string, string> dict { get; }  
    void CreatePDF(); 
} 

public class PDFBuilder : IPDFBuilder 
{ 
    public string templatefilename { get; private set; } 
    public string templatefilepath { get; private set; } 
    public Dictionary<string, string> dict { get; private set; } 

    public PDFBuilder(string templatefilename, string templatefilepath, Dictionary<string, string> dict) 
    { 
     this.templatefilename = templatefilename; 
     this.templatefilepath = templatefilepath; 
     this.dict = dict; 
    } 

    public void CreatePDF() { 
     //Do something 
    } 
} 

Это PDFBuilder может и будет использоваться в нескольких контроллерах, например:

public class KeuringController : Controller 
{ 
    private IPDFBuilder _PDFBuilder; 
    public KeuringController(IPDFBuilder pdfBuilder) 
    { 
     _PDFBuilder = pdfBuilder; 
    } 
    //Action methods that use `PDFBuilder` below... 
} 

Однако, я не могу установить свойство PDFBuilder в классе запуска (где регистрация DI является неоспоримым сделана), поскольку разные контроллеры будут использовать разные значения для свойств класса PDFBuilder. 1 простым решением было бы просто сделать сеттеры свойств общедоступными, поэтому в методе действий я могу установить значения, а затем позвонить CreatePDF(). Однако это не так. Другим простым решением было бы удалить свойства класса и просто передать 3 свойства PDFBuilder как свойства метода к CreatePDF метода, как это:

public void CreatePDF(string templatefilename, string templatefilepath, Dictionary<string, string> dict) { 
     //Do something 
    } 

Но теперь давайте говорить, что моя PDFBuilder whould есть 10 способов, которые все нуждаются в них 3 объекта. Тогда это не правильное решение?

Что было бы правильным решением тогда? Я столкнулся с этой проблемой несколько раз с различными реализациями классов/интерфейсов и хотел бы иметь некоторую помощь при проектировании в этих ситуациях.

+1

Откуда берутся значения этих параметров/свойств? Файл конфигурации? Или от пользователя? –

ответ

4

Вы вводите данные времени выполнения в конструктор вашего компонента, который является bad thing. Решение состоит в том, чтобы переместить эти значения во время выполнения из конструктора в метод CreatePDF:

public interface IPDFBuilder 
{ 
    void CreatePDF(string templatefilepath, string templatefilename, 
     Dictionary<string, string> dict); 
} 
+0

Не совсем ясно, являются ли данные времени выполнения. Возможно, это данные конфигурации, которые поступают из файла конфигурации. –

+0

@YacoubMassad: Вопрос гласит: «потому что разные контроллеры будут использовать разные значения для свойств». Это привело меня к выводу, что это данные времени выполнения. Но вы правы, все равно могут быть данные конфигурации, и это изменит ответ. – Steven

+1

Извините за поздний отклик, я точно знаю данные во время выполнения! Я буду отмечать это как ответ, потому что ссылка, которую нам дал Стивен, является отличным руководством. –

0

Вы можете создать подкласс (или прототип, в зависимости от ваших требований) различные виды PDFBuilders и вводят их в соответствии классов.

Я не знаю, какой DI Framework вы используете, но я уверен, что это возможность рассказать структуре, какую зависимость вы хотите вводить в определенных классах.

Редактировать: Имейте в виду: это решение неприменимо для значений, известных во время выполнения.

0

Существует два способа сделать то, что вы хотите:

1) Create factory for builder. 

2) Create configurator for builder. 

При создании завода, вы в основном указать способ создания объекта и поэтому может свободно устанавливать все, что вы хотите в различные реализации для разных строителей:

public inteface IPDFBuilderFactory 
{ 
    IPDFBuilder Create(); 
} 

Вам нужно будет передать все зависимости - это недостаток. Мне лично этот метод не нравится.

Другой способ, чтобы создать конфигурацию, как это:

public interface IPDFConfiguration 
{ 
    string templatefilename {get;} 
    string templatefilepath {get;} 
    Dictionary<string, string> dict {get;} 
} 

и передать его в качестве аргумента в конструктор:

public PDFBuilder(IPDFConfiguration configuration) 
{ 
    ... 
} 

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

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

Выберите, что подходит вам лучше всего.