2016-07-05 10 views
4

私はDIについて学び、IoCの理解を深め、その他の利点を得ようとしています。依存性注入とプロジェクトの参照

私はUIプロジェクト(MVC)、BusinessLogicプロジェクト、DataAccessプロジェクトを持つプロジェクトを持っています。私はSharedLibプロジェクトも持っています。すべてのプロジェクトにはSharedLibへの参照があります。 UIにはBusinessLogicへの参照があり、BusinessLogicにはDataAccessへの参照があります。

インターフェイスを追加します。だから私は自分のDataAccessに行き、各クラスのためにInterfaceを追加し、それらのメソッドをpopulatします。私はビジネスロジック層でも同じことをしています。

私はUIプロジェクトのBusinessLogicクラスでインスタンス化するDataAccessクラスを挿入するために、私のDataプロジェクトへの参照が必要です。なぜなら、UIプロジェクト(正しく、私は思う) IDataAccess 'インターフェースがあります。私が見ることができる唯一の修正点は、私のDAプロジェクトにプロジェクト参照をUIに追加することです。これは間違っています。

そして、Unityをコンテナとして追加しようとすると(ある日、将来すべての作業が完了したら)、UIプロジェクトのインターフェイス/クラス関係を初期化したい - 同じ問題。

多分、インターフェイスはいくつかの共有プロジェクトに入っている必要がありますか?または1つのプロジェクトをアップ?これをどのように扱うべきですか?

+0

プロジェクト参照(例えば、循環参照)及びDIは、2つの別々の関心事です。参照を追加することは、必ずしも悪いことではありません。適切な答えは、どのツールがDIに使用されているかによって異なります。私はあなたが快適であるDIツールを調査し、ニーズに合わせて機能を評価することをお勧めします。 –

+0

私が上記のことを少し詳しく説明します。多くのDIツールでは、どのようなサービスがどのインタフェースに登録されているのかをどこかに配線しなければなりません。一度登録すると、手動でインスタンスを手動で作成するわけではありません。 DIを適切に使用すると、UIはビジネスオブジェクトのインスタンスを作成せず、UIのコントローラのコンストラクタに注入され、DataAccessはビジネスロジッククラスに注入されます。例えば。 DIツールがどのように動作するのかを理解するのに、特にMVCアプリケーションの場合、特別な生き物として、もう少し時間を費やしています。 –

+0

また、クラスを所属するアセンブリの内部に作成し、インタフェースを公開することだけができます。 AutofacのようなDIコンテナは、すべてのクラスをアセンブリからワイヤリングし、それらのインターフェイスだけで使用できるようにします。 –

答えて

4

プロジェクト間で参照が必要ない場合は、ファクトリ/抽象ファクトリを調べることができます。

あなたのUIはビジネスレイヤを知っているので、データレイヤの使用方法を知っているビジネスレイヤのファクトリを定義する必要があります。次に、コンポジションルート(この例ではUIプロジェクト)ですべてのDIを処理します。

、あなたの質問

データ層

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としてコンソールアプリケーションを使用して、以下の簡単な例

UI

実際の世界の例では、何のためにも抽象化されているように見えるので、それは理にかなった例です。

データレイヤーのデータベース、XMLファイルなどにさまざまなデータアクセスクラスが存在する可能性があります。そのため、ビジネスレイヤーごとにファクトリを定義することができます。抽象的な工場

工場を使用して


データ層の核心について、より多くのロジックを含む、または抽象工場としてビジネスロジック層への個々の工場のセットを提供することができます。

ビジネス層

あなたが代わりにコンクリート工場

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

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

と、このような

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

などのビジネス層に抽象工場を持っているかもしれません(追加の具体的な工場を持っているかもしれません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(); 
    } 
} 

データ層のようになりますあなたのビジネス層は、もはやあなたは、この例では、データ層に移動することができますので、あなたのUIにIDataAccessFactoryを提供する必要があります

。だから、データ層クラスは

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