2016-11-07 68 views
2

我有使用DI與構造函數屬性的問題。我正在根據我的IPDFBuilder構建PDFBuilderDI使用動態構造函數注入

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登記beeing完成),因爲不同的控制器將對PDFBuilder類的屬性使用不同的值。一個簡單的解決方案就是讓屬性的setter公開,以便在一個操作方法中我可以設置這些值,然後調用CreatePDF()。然而這並不正確。另一種簡單的解決辦法是刪除類的屬性,只是傳遞的PDFBuilder作爲方法屬性的3個屬性的CreatePDF方法是這樣的:

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

但是,現在讓我們說,我PDFBuilder對子級有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框架,但我很確定這是一個選項,告訴框架你想在特定的類中注入什麼樣的依賴關係。

編輯:請記住:此解決方案不適用於運行時已知的值。

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改變他們一段時間。您也可以自由初始化此配置 - 常量,配置,數據庫等。

缺點之一 - 您的配置會隨着時間的推移變得非常笨拙,而且不會重構它,這對其他人來說是黑洞,所以要小心。

選擇最適合您的是什麼。