2016-07-05 80 views
4

我想了解DI,有一個更好的瞭解國際奧委會,以及其他好處。依賴注入和項目引用

預DI,我有一個具有UI項目(MVC),一個BusinessLogic項目和數據訪問項目的項目。我也有一個SharedLib項目。所有項目都有對SharedLib的引用。 UI具有對BusinessLogic的引用,並且BusinessLogic具有對DataAccess的引用。

我想現在添加接口。所以我去我的DataAccess,併爲每個類添加一個接口,並用他們的方法填充它們。我對業務邏輯層也一樣。

但爲了注入DataAccess類,我在UI項目的BusinessLogic類中實例化,我需要一個對Data項目的引用,因爲UI項目(正確地說,我認爲)不知道' IDataAccess'界面。我能看到的唯一解決方法是在我的UI項目中添加項目引用到我的DA項目中 - 這看起來不對。

如果我嘗試添加團結作爲我的容器(有一天,在未來,一旦我的工作如何,所有的作品),並希望我的初始化界面/用戶界面中的項目類關係 - 同樣的問題。

也許接口必須在某些共享的項目去了?還是一個項目了?這應如何處理?

+0

項目引用(例如循環引用)和DI是兩個單獨的顧慮。添加引用可能不一定是件壞事。正確的答案取決於DI使用的是什麼工具。我建議你調查一下你喜歡的任何DI工具,並根據你的需求評估它的功能集。 –

+0

爲了詳細闡述我上面所說的內容;在許多DI工具中,你必須在某個地方連接哪些服務已註冊到哪些接口。一旦註冊,您就不會自己手動創建實例。當您正確使用DI時,您的UI將不會創建您的業務對象的實例,它將被注入到您的UI控制器的構造函數中,就像將DataAccess注入到業務邏輯類中一樣。例如。花更多時間瞭解DI工具的運行方式,尤其是MVC應用程序,因爲它們是一種特殊的生物。 –

+0

您也可以將您的類放入其所屬的程序集內部,並僅將接口公開。像Autofac這樣的DI容器可以連接程序集中的所有類,並僅通過它們的接口使它們可用。 –

回答

4

如果你不想讓你可以看看工廠/抽象工廠項目之間的引用。

你的UI知道你的業務層,所以你要在它知道如何使用數據層業務層定義一個工廠。然後你在你的組合根目錄下處理你的所有DI(本例中的UI項目)。

下面使用一個控制檯應用程序的UI,堅持你在你的問題

數據層

public interface IDataAccess 
{ 
    string GetData(); 
} 

public class XmlDataAccess : IDataAccess 
{ 
    public string GetData() 
    { 
     return "some data"; 
    } 
} 

業務層

public interface IDataAccessFactory 
{ 
    IDataAccess GetDataAccess(); 
} 

public class XmlDataAccessFactory : IDataAccessFactory 
{ 
    public IDataAccess GetDataAccess() 
    { 
     return new XmlDataAccess(); 
    } 
} 

public class BusinessLogic 
{ 
    IDataAccessFactory dataAccessFactory; 

    public BusinessLogic(IDataAccessFactory dataAccessFactory) 
    { 
     this.dataAccessFactory = dataAccessFactory; 
    } 

    public void DoSomethingWithData() 
    { 
     IDataAccess dataAccess = dataAccessFactory.GetDataAccess(); 
     Console.WriteLine(dataAccess.GetData()); 
    } 

    public string GetSomeData() 
    { 
     IDataAccess dataAccess = dataAccessFactory.GetDataAccess(); 
     return dataAccess.GetData(); 
    } 
} 
指出引用一個簡單的例子

UI

static void Main(string[] args) 
{ 
    IUnityContainer container = new UnityContainer(); 
    container.RegisterType<IDataAccessFactory, XmlDataAccessFactory>(); 

    var logic = container.Resolve<BusinessLogic>(); 
    logic.DoSomethingWithData(); 

    string useDataInUI = logic.GetSomeData(); 
    Console.WriteLine("UI " + useDataInUI); 

    Console.ReadKey(); 
} 

這是一個人爲的例子,所以它看起來像抽象白白,但與現實世界例如,它會更有意義。

例如您可能會在數據層數據庫,xml文件等中擁有大量不同的數據訪問類,因此您可以爲業務層中的每個數據庫定義一個工廠。


使用抽象工廠

工廠可能含有更大量的邏輯有關數據層的細節問題,或者作爲一個抽象工廠提供一套個別工廠到商業邏輯層。

業務層

您可以改爲在業務層如

public interface IPlatformFactory 
{ 
    IDataAccessFactory GetDataAccessFactory(); 
    IPricingFactory GetPricingFactory(); // might be in the business project, or another project referenced by it 
} 

抽象工廠用混凝土廠

public class WebPlatformFactory : IPlatformFactory 
{ 
    IDataAccessFactory GetDataAccessFactory() 
    { 
     return new XmlDataAccessFactory(); 
    } 

    IPricingFactory GetPricingFactory() 
    { 
     return new WebPricingFactory(); // not shown in the example 
    } 
} 

(您可能需要額外的具體工廠如RetailPlatformFactory等)

BusinessLogic類現在看起來像

public class BusinessLogic 
{ 
    IPlatformFactory platformFactory; 

    public BusinessLogic(IPlatformFactory platformFactory) 
    { 
     this.platformFactory = platformFactory; 
    } 

    public void DoSomethingWithData() 
    { 
     IDataAccessFactory dataAccessFactory = platformFactory.GetDataAccessFactory(); 
     IDataAccess dataAccess = dataAccessFactory.GetDataAccess(); 
     Console.WriteLine(dataAccess.GetData()); 
    } 

    public string GetSomeData() 
    { 
     IDataAccessFactory dataAccessFactory = platformFactory.GetDataAccessFactory(); 
     IDataAccess dataAccess = dataAccessFactory.GetDataAccess(); 
     return dataAccess.GetData(); 
    } 
} 

數據層

業務層不再需要提供一個IDataAccessFactory你的UI,所以你可以在這個例子中它移動到你的數據層。因此,數據層類將是

public interface IDataAccess 
{ 
    string GetData(); 
} 

public class XmlDataAccess : IDataAccess 
{ 
    public string GetData() 
    { 
     return "some data"; 
    } 
} 

public interface IDataAccessFactory 
{ 
    IDataAccess GetDataAccess(); 
} 

public class XmlDataAccessFactory : IDataAccessFactory 
{ 
    public IDataAccess GetDataAccess() 
    { 
     return new XmlDataAccess(); 
    } 
} 

UI

現在你會在UI你配置容器,並執行類似的動作爲

static void Main(string[] args) 
{ 
    IUnityContainer container = new UnityContainer(); 
    container.RegisterType<IPlatformFactory, WebPlatformFactory>(); 

    var logic = container.Resolve<BusinessLogic>(); 
    logic.DoSomethingWithData(); 

    string useDataInUI = logic.GetSomeData(); 
    Console.WriteLine("UI " + useDataInUI); 

    Console.ReadKey(); 
} 

然後UI知道關於數據層/訪問沒有任何內容,它只是將工廠創建交給業務層,業務層持有數據(和定價)引用。

一些建議閱讀:

Composition Root

Implementing an Abstract Factory

Compose object graphs with confidence

+0

好貼!我正在嘗試通過它。謝謝。 – Craig