簡體   English   中英

使用帶有運行時參數的構造函數進行Unity依賴注入

[英]Dependency Injection With Unity Using Constructors With Runtime Parameters

我已經掌握了依賴注入的基礎知識,但是我一直在努力將其正確地整合到使用Unity的MVC API C#應用程序中。 我的問題是我將擁有一個具有方法的控制器,並且在該方法中它將具有兩個對象。 這些對象之一將依賴於數據訪問層,而另一個則不依賴。 我不太確定該如何設置。

可以說我有一個具有以下方法的控制器,該控制器可從搜索對象中獲取用戶。 它還使用SearchParameters對象執行搜索。 如果不使用名稱進行搜索,則會得到所有結果,或者如果輸入名稱,則將獲得具有該名稱的所有用戶。

public Users[] GetUsers(string name) {
    Company.SearchParameters searchParams = new Company.SearchParameters(name);
    Company.UserSearchService searchService = new Company.UserSearchService(searchParams);

    return searchService.Search();
}

當然,這是一個超級簡化的版本,但是在這種情況下,Search方法中的UserSearchService正在執行顯式數據庫調用。 所以我知道這是我必須給予的依賴。 SearchParameters實際上只是一個保存數據的類。

這是我不確定下一步該怎么做的地方。 Controller本身沒有依賴項,但是由於UserSearchService確實不知道如何使用統一性,因此我正確地設置了它並考慮了構造函數的運行時值。 我也不確定是否應該將SearchParameters視為依賴項。

另外,如果這很重要,則SearchParameters和UserSearchService沒有任何類型的支持接口,並且此控制器上還有其他方法可以與需要數據訪問層依賴項的其他類(例如Company.UserAccount)進行交互。

我在這里看到兩個任務。 首先是重構,其中靜態依賴項必須替換為接口。 第二項任務是在IoC容器中注冊您的東西。

對於第一個任務,最低要求是用UserSearchService IDatabase替換對UserSearchServiceDatabase所有引用(以便也可以對其進行UserSearchService )並將其傳遞給構造函數(構造函數注入)。 為了能夠向服務提供IDatabase實例,您必須為控制器創建相同的依賴項(再次構造函數注入)。 然后注冊IDatabase執行如圖這篇文章

更新

我同意必須從控制器中刪除依賴項。 正如您@Topojijo所建議的,在這種情況下可以使用UserSearchService的工廠。 猜測您有幾個服務需要為每個服務提供工廠,如果服務數量很大,可能會產生間接費用。 在這種情況下,最好直接從Unity容器中解析服務並將searchParams移至Search方法:

public Users[] GetUsers(string name) {
    Company.SearchParameters searchParams = new Company.SearchParameters(name);
    Company.UserSearchService searchService = container.Resolve<Company.UserSearchService>();

    return searchService.Search(searchParams);
}

搜索參數不應是構造函數的一部分; 它應該是“搜索”方法的一部分。 在UserSearchService類(封裝)之外,甚至都不應該知道SearchParameter對象。 如neleus建議的那樣,應該進行一些重構。 至少,為了使事情順利進行,應該將其重構為類似以下內容:

public Users[] GetUsers(string name) {
    // Or however you end up with your UserSearchService object.  
    // Ideally as an interface and an injected dependency...
    Company.UserSearchService searchService = new Company.UserSearchService();

    return searchService.Search(name);
}

Company.UserSearchService:

public Users[] Search(string name) {
    // A factory would be a better option.  This should also be an interface.
    Company.SearchParameters searchParams = new Company.SearchParameters(name);

    // Your logic here
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM