1

NInjectを使用して(シングルトンスコープの)Fooサービスの既知の固定リストを解決しようとしています。この解決は、FooProviderのコンストラクターで行われます。問題は、各Fooにもこのプロバイダーが必要になることです。

public interface IFoo { }
public interface IFooProvider { }

public class Foo : IFoo
{
    private readonly IFooProvider _provider;

    public Foo(IFooProvider provider)
    {
        _provider = provider;
    }
}

public class FooProvider : IFooProvider
{
    private List<IFoo> _allFooServices;

    public FooProvider(IKernel kernel)
    {
        _allFooServices = kernel.GetAll<IFoo>().ToList();
    }
}

public class Program
{
    private static void Main(string[] args)
    {
        var IoC = new StandardKernel();

        IoC.Bind<IFoo>().To<Foo>().InSingletonScope();
        IoC.Bind<IFooProvider>().To<FooProvider>().InSingletonScope();

        var foo = IoC.Get<IFoo>();
    }
}

ここには論理的な循環ループがあり、明らかにスタックオーバーフローはそれが下がっていることを示しています。ただし、両方のインターフェイスをシングルトンにバインドしています。

それについて考える; IFooを解決しようとしますが、IFooProviderの解決が必要であり、それ自体にIFooのリストが必要です...しかし、まだ解決しようとしているため、IFooシングルトンについてはまだ解決していません。

では、どうすればこれを回避できますか?

[編集]可能な解決策; IFooサービスインスタンスのバッファリングを遅らせます。

public FooProvider(IKernel kernel)
{
    _kernel = kernel;
}

public IFoo Find(object context)
{
    if (_allFooServices == null)
        _allFooServices = _kernel.GetAll<IFoo>().ToList();

    return _allFooServices.Where(...

[なぜ?]

一般的な考え方は、アンチパターンとして説明されているように、サービスロケーターパターンを回避することです。したがって、実行時に依存性注入を介してサービスを解決しようとするのではなく、セットアップ中にサービスのリストを取得しようとします。ただし、これに伴う問題は、サービスのいずれかが他のサービスを見つけたい場合、上記の問題があることです。

4

3 に答える 3

1

それらのいずれかでプロパティ注入を使用できます。

public interface IFoo
{
}

public interface IFooProvider
{
}

public class Foo : IFoo
{
   [Inject]
   public IFooProvider Provider { get; set; }
}

public class FooProvider : IFooProvider
{
   private List<IFoo> _allFooServices;

   public FooProvider(IKernel kernel)
   {
      _allFooServices = kernel.GetAll<IFoo>().ToList();
   }
}

private static void Main(string[] args)
{
   var IoC = new StandardKernel();
   IoC.Bind<IFoo>().To<Foo>().InSingletonScope();
   IoC.Bind<IFooProvider>().To<FooProvider>().InSingletonScope();

   var foo = IoC.Get<IFoo>();
 }
于 2013-03-04T13:29:39.527 に答える
1

この循環依存を Ninject で解決することはできません。このようなオブジェクト グラフを手動で作成することさえできません。

まず、少なくとも 1 つのコンストラクターから循環依存関係を削除する必要があります。この依存関係をプロパティに移動し、プロパティ インジェクションを使用できます。

public class Foo : IFoo
{
   [Inject]
   public IFooProvider Provider { get; set; }
}

サービスロケーター パターンを回避したい場合はIKernel、コンストラクターから依存関係を削除し、代わりに登録された実装FooProviderのコレクションの注入を使用する必要があります。IFoo

public class FooProvider : IFooProvider
{
    private List<IFoo> _allFooServices;

    public FooProvider(IEnumerable<IFoo> fooServices)
    {
        _allFooServices = fooServices.ToList();
    }
}
于 2013-03-05T08:37:30.723 に答える
0

本当にこれは悪い設計のように思えますが、質問に直接答えるには、コンストラクターで _allFooServices をインスタンス化しないでください。次のようなことができます。

private List<IFoo> _allFooServices;
private List<IFoo> AllFooServices
{
    get { return _allFooServices ?? (_allFooServices = Kernel.GetAll<IFoo>().ToList()) }
}

おそらく、Foo ではなく、より具体的な例を選択できます。

于 2013-03-04T13:21:41.820 に答える