2012-01-26 5 views
6

さて、最近私は読んだことがありますが、wikiページで「貧乏人のDI」と呼ばれる理由を理解するのが難しいです。悲しい事は、私が(=それを得ることはありません、まだwikiにすべての自分のページの上に行き、ある工場DIよりも問題(または一般的なIOCコンテナ)を理解できませんでしたか?

通常

私はそうのようなDIを扱う工場のパターンで私のサービスクラスをラップします:。

public static class SomeTypeServiceFactory 
{ 
    public static SomeTypeService GetService() 
    { 
     SomeTypeRepository someTypeRepository = new SomeTypeRepository(); 
     return = new SomeTypeService(someTypeRepository); 

    } 

} 

モジュールのような多くのことを思える私に:

各クラスは、それが具体的な実装にコンストラクタのBINDそれはモジュールとあなた関連付けられていますninjectコードが1つの以下のラインですが、私はただ見ていないのですだろう
public class WarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<IWeapon>().To<Sword>(); 
     Bind<Samurai>().ToSelf().InSingletonScope(); 
    } 
} 

。利点は、いつでもコンストラクタを追加/削除したり、インターフェイスコンストラクタの実装では、モジュールを工場と同じように変更する必要がありますか?だからここで優位を見ていない。

public static TServiceClass GetService<TServiceClass>() 
     where TServiceClass : class 
    { 
     TServiceClass serviceClass = null; 

     string repositoryName = typeof(TServiceClass).ToString().Replace("Service", "Repository"); 
     Type repositoryType = Type.GetType(repositoryName); 

     if (repositoryType != null) 
     { 
      object repository = Activator.CreateInstance(repositoryType); 
      serviceClass = (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository}); 
     } 

     return serviceClass; 
    } 

しかし、これは2つの理由のために安っぽいです:1)その命名規則に厳密に依存し、2)それは仮定

は、それから私は、私はそうのような一般的な慣習に基づく工場を考え出すことができると思いましたリポジトリは決してコンストラクタ(真ではない)を持たず、サービスの唯一のコンストラクタはそれに対応するrepo(真ではない)になります。私はと言っていました。「これはIoCコンテナを使用すべき場所ですね、ここは素晴らしいでしょう!これで私の研究が始まりました...しかし、私はそれを見ていないだけで、それを理解するのに苦労しています...

ninjectは、特定の宣言なしでクラスのコンストラクタを自動的に解決する方法はありますか私のジェネリック工場で使うのは素晴らしいです(私はリフレクションを使って手動で行うこともできますが、それはパフォーマンスヒットで、自分のページではリフレクションを使用しないと言っています)。

この問題についての啓蒙活動や、それが私のジェネリック工場でどのように使用されるかを示すことは、非常に高く評価されます。

EDIT:

public static class EntityServiceFactory 
{ 
    public static TServiceClass GetService<TServiceClass>() 
     where TServiceClass : class 
    { 
     IKernel kernel = new StandardKernel(); 

     return kernel.Get<TServiceClass>(); 
    } 
} 

すごい:I以下の説明のおかげで完全にninjectの素晴らしさを理解するために巧みだったと私の一般的な工場は、次のようになりますので、

回答。具象クラスは暗黙のバインディングを持っているので、すべてが自動的に処理されます。

+0

通常の壊れたレコードのコメント:[私のマーク・シーマン.NET帳に依存性注入](http.commanning.com/seemann)に実行します。私はあなたがなぜDIとDIコンテナの所有権を1週間以内に持っているのか自信がないとは想像できません。 –

答えて

7

IoCコンテナの利点は、プロジェクトの規模とともに大きくなります。小規模プロジェクトの場合、あなたの工場のような "Poor Man's DI"に比べて利益は最小です。数千のクラスを持ち、いくつかのサービスが多くのクラスで使用されている大規模なプロジェクトを想像してみてください。この場合、これらのサービスがどのように解決されたかについて一度だけ言わなければなりません。工場では、すべてのクラスで何度も何度もやり直さなければなりません。

例:サービスMyService : IMyServiceAが必要な場合は、IMyServiceが必要です。あなたの工場でこれらのタイプを解決する方法をNinjectに伝える必要があります。ここでの利点は最小限です。しかし、あなたが成長し、すぐにIMyServiceに依存するクラスBを追加すると、Ninjectにどのように解決するかをBに伝える必要があります。 NinjectはすでにIMyServiceの入手方法を知っています。一方、工場では、BがどのようにしてIMyServiceを取得するかを再度定義する必要があります。

これをさらに進めてください。ほとんどの場合、バインディングを1つずつ定義するべきではありません。代わりに、コンベンションベースの設定(Ninject.Extension.Conventions)を使用してください。これにより、クラスをグループ化して(サービス、リポジトリ、コントローラ、プレゼンター、ビューなど)、同じ方法でそれらを構成できます。例えば。 Serviceで終わるすべてのクラスがシングルトンであり、すべてのインタフェースを公開することをNinjectに伝えます。そうすれば、1つの設定が可能になり、別のサービスを追加するときに変更する必要はありません。

また、IoCコンテナは単なる工場ではありません。はるかに多くがあります。例えば。ライフサイクル経営管理論、傍受、....

kernel.Bind(
    x => x.FromThisAssembly() 
      .SelectAllClasses() 
      .InNamespace("Services") 
      .BindToAllInterfaces() 
      .Configure(b => b.InSingletonScope())); 
kernel.Bind(
    x => x.FromThisAssembly() 
      .SelectAllClasses() 
      .InNamespace("Repositories") 
      .BindToAllInterfaces()); 
+0

私は(他の答えと同じ質問を参照してください)、実際には、私は工場の一般的な実装を行うのに役立つことはありませんか?あるいは、何らかの形で私が宣言することなく依存関係を自動的に解決しますか?単一のサービスクラスごとにモジュール/ファクトリを持たない限り、また、私のレポやサービスにさまざまな量の注射があるとすれば、実際には慣習は使えませんでしたか? – SventoryMang

+1

あなたはninjectの仕組みを誤解しているようです。コンストラクターは、構成から正しい依存関係を取得しようとします。したがって、異なる数の依存関係を持つクラスは、同じ規約を使用して簡単に構成できます。 –

+0

うーん、私は今思うよ。したがって、それは私の一般的な工場のために私を助けることができない、正しい?私はまだ注入を宣言的にある時点で設定しなければなりません。つまり、ここでジェネリックを実際に行うことはできません。可変数の依存関係を持つ規則を使用する例がありますか?私は自分のシナリオにサイト上のものを外挿するのに苦労しています。 – SventoryMang

2

があるために完全にあなたの工場コードを読んでくださいanalagous:

public static class SomeTypeServiceFactory 
{ 
    public static ISomeTypeService GetService() 
    { 
     SomeTypeRepository someTypeRepository = new SomeTypeRepository(); 

     // Somewhere in here I need to figure out if i'm in testing mode 
     // and i have to do this in a scope which is not in the setup of my 
      // unit tests 

     return new SomeTypeService(someTypeRepository); 
    } 

    private static ISomeTypeService GetServiceForTesting() 
    { 
     SomeTypeRepository someTypeRepository = new SomeTypeRepository(); 
     return new SomeTestingTypeService(someTypeRepository); 
    } 
} 

そしてNinjectでequilvalentは次のようになります。ここでは

public class WarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<ISomeTypeService>().To<SomeTypeService>(); 
    } 
} 

public class TestingWarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<ISomeTypeService>().To<SomeTestingTypeService>(); 
    } 
} 

は、あなただけの違いことを保証し、宣言的依存関係を定義することができますテストコードとプロダクションコードの間にはセットアップ段階が含まれます。

IoCの利点は、インターフェイスまたはコンストラクタが変更されるたびにモジュールを変更する必要がないということではなく、依存関係を宣言的に宣言でき、異なるモジュール目的。

+0

私は実際に工場の一般的な実装をするのに役立つわけではありません。あるいは、何らかの形で私が宣言することなく依存関係を自動的に解決しますか?単一のサービスクラスごとにモジュール/ファクトリを持たない限り、 – SventoryMang

関連する問題