私は Dependency Injection の初心者であり、Ninject をいじって小さなテスト アプリケーションを作成し、概念を理解しようとしています。Mark Seemann の.NET での Dependency Injection は、私の読書リストの次です。
簡単なテストで遭遇した 1 つの問題は、クラスがその型の新しいインスタンスをインスタンス化できるケースを処理する方法がわからないことです。例として、ボタンのあるフォームがあります。ユーザーがボタンをクリックすると、フォームは同じタイプの別のフォームを作成します。
DI を使用しない場合、上記のシナリオではnew
、元のフォームのクリック イベント ハンドラーで別のフォーム インスタンスを作成するだけです。好ましい方法は、抽象ファクトリを使用してインスタンスを作成し、それにクラスを依存させることであると私は理解しています (そして、私はこの分野では素朴かもしれません)。
以下は、私が試したコードです (フォームとは関係なく、単純なクラスのみ)。これは、循環依存関係のために機能しません。なぜそれが発生しているのかがわかります。new
手動で何かをする必要のない良い解決策が思い浮かびません。キーピースが欠けているような気がします。
public interface IMainClass
{
IMainClass CreateNew();
void Do();
}
public interface IMainClassFactory
{
IMainClass CreateNew();
}
public class MainClassFactory : IMainClassFactory
{
private readonly IMainClass _mainClass;
public MainClassFactory(IMainClass mainClass)
{
_mainClass = mainClass;
}
public IMainClass CreateNew()
{
return _mainClass;
}
}
public class MainClass : IMainClass
{
private readonly IMainClassFactory _mainClassFactory;
public MainClass(IMainClassFactory mainClassFactory)
{
_mainClassFactory = mainClassFactory;
}
public IMainClass CreateNew()
{
return _mainClassFactory.CreateNew();
}
public void Do()
{
Console.WriteLine("Do from Main Class");
}
}
public class Program
{
public static void Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<IMainClassFactory>().To<MainClassFactory>();
kernel.Bind<IMainClass>().To<MainClass>();
var mainClassFactory = kernel.Get<IMainClassFactory>();
var mainClass = mainClassFactory.CreateNew();
mainClass.Do();
Console.WriteLine("Press <ENTER> to exit...");
Console.ReadLine();
}
}
このコードが間違っていることはわかっています。
- IMainClass は IMainClassFactory を実装する必要がありますか? それは問題ですか?
kernel.Bind<IMainClass>().To<MainClass>();
正しくないようですが、どうすればよいかわかりません- 独自のオブジェクトを作成することは
new
完全に禁止されていますか? - Service Locator アンチパターンを使用しないことについては、かなりよく理解していると思います。クラスに IOC コンテナーを認識させたくありません。
これらのタイプのシナリオは常に発生していると確信しているため、一般的なケースで推奨されるソリューションを探しています。可能であれば、別の実装に移行したい場合に備えて、Ninject 固有のエキゾチックな機能の使用を避けたいと考えています。
編集 1: 'Autofac Circular Component Dependency Detected' エラー 私の読み間違いかもしれませんが、ハリウッド原則に違反しているように見えます