2015-12-03 92 views
2

我的應用程序使用了一堆Service類,其中許多類都有一個支持Repository類。當我的應用程序啓動時,我創建了一個新的Unity容器,其中包含創建所有Service和Repository類的句柄,並執行所有依賴注入。我見過的例子說,通過一個全局容器來擁有Unity容器是一種不好的做法,所以在它完成創建它需要創建的所有對象後,它就超出了範圍。然後這些對象在整個程序的其餘部分中傳遞。連接字符串代理?

我的問題是,我有一個「設置」窗口,讓用戶更改數據庫名稱和服務器。但是,所有Services對象都已支持通過注入原始數據庫名稱和服務器創建的Repository對象。所以我必須更改已經創建的所有Repository對象的數據庫連接字符串。

我在考慮製作類似於IDatabaseConnectionStringProxy接口的東西,並讓我的所有Repository對象都有對該類型的單個對象的引用,而不是每個存儲庫都存儲其連接字符串明確性。然後我可以讓我的「設置」窗口更新所有存儲庫類指向的單個代理對象上的連接字符串。這會是一個好的設計,還是一種不好的做事方式?如果這不是一個好主意,我該如何處理?

+0

在詢問用戶輸入之前創建這些對象是否有意義?是否有一個默認的連接字符串直到用戶更改設置才使用? –

+0

是的,默認情況下程序是使用默認連接字符串安裝的。然後,如果用戶更改了連接,那麼該數據庫名稱和服務器將在下次啓動該程序時成爲新的默認值。幾乎所有的程序都需要數據庫訪問,所以它需要從一開始就創建這些對象。 –

+0

*「下一次啓動程序」*你不能只是將新的連接字符串保存在配置文件中,然後繼續? –

回答

4

這聽起來像是一個變異的頗具異國情調的未來生活方式描述的第272頁my book。我認爲你應該可以用Decorator來解決這個問題,而不是發明一個新的界面。

首先,讓我們想象一下所涉及的類型是什麼樣子。這聽起來像你有一些存儲庫接口。讓我們把一個代表庫IFooRepository

public interface IFooRepository 
{ 
    Foo Read(int id); 
} 

它還聽起來像是你有跟數據庫的具體實現。良好的措施,讓我們給具體的類Inspection Properties,這樣我們就可以查詢庫對象要問它的連接字符串,它使用了:

public class SqlFooRepository : IFooRepository 
{ 
    private const string connectionString; 

    public SqlFooRepository(string connectionString) 
    { 
     if (connectionString == null) 
      throw new ArgumentNullException("connectionString"); 

     this.connectionString = connectionString; 
    } 

    public string ConnectionString 
    { 
     get { return this.connectionString; } 
    } 

    public Foo Read(int id) 
    { 
     // SQL query code goes here... 
    } 
} 

這使您可以創建一個裝飾(或者它是一個Decoraptor):

public class ConnectionstringAwareFooRepository : IFooRepository 
{ 
    private SqlFooRepository repo; 

    public Foo Read(int id) 
    { 
     var connectionstring = 
      ConfigurationManager.ConnectionStrings["foo"].ConnectionString; 

     if (this.repo == null || 
      this.repo.ConnectionString != connectionString) 
      this.repo = new SqlFooRepository(connectionString); 

     return this.repo.Read(id); 
    } 
} 

這種設計的好處是,它完全從屏蔽處理髮現新的連接字符串的管理方面的客戶端代碼。所有客戶看到的是IFooRepository

但請注意,上述示例不是線程安全的。如果您需要在多線程環境中使用此解決方案,則需要使其成爲線程安全的。

由於ConnectionstringAwareFooRepository類從配置文件中讀取,我強烈建議您將它與您的代碼庫中的Composition Root放在同一部分。

+0

這是一個有趣的解決方案。我從來沒有聽說過_Future_生活方式。感謝您向我介紹這一點。我將閱讀有關它。我有點擔心''ConnectionStringAwareFooRepository'中的'ConfigurationManager'引用(特別是它是一個靜態類),因爲我一直在努力確保所有的依賴關係都被注入,並且'ConfigurationManager'看起來像它引入了外部依賴。在你看來,這種類型的「配置設置」外部依賴性好嗎? –

+0

@BenRubin這就是爲什麼我建議你把這個類放到你的Composition Root中。您需要從'.config'文件的某個位置讀取配置值,並且在某處是組合根。 –

+0

@BenRubin儘管如此,如果您寧願將'ConnectionstringAwareFooRepository'放在其他位置,那麼注入一個可以爲您讀取連接字符串的抽象工廠,並通過從配置文件中讀取來實現該抽象工廠。 –