9

http://markmail.org/message/6rlrzkgyx3pspmnfで説明されている問題と非常によく似た問題があります。これは、異なるサービス タイプを使用してアクセスしている場合に、シングルトンが実際に複数のインスタンスを作成することに関するものです。

私はコンパクトフレームワーク用のNinject 2の最新リリースを使用していますが、私が抱えている正確な問題は、同じプロバイダーメソッドを次のようにバインドした場合です。

Func<Service> serviceCreator = () => new Service(false);
kernel.Bind<IService>().ToMethod(serviceCreator).InSingletonScope();
kernel.Bind<Service>().ToMethod(serviceCreator).InSingletonScope();

IService と Service の両方として解決すると、Service の 2 つのインスタンスが作成されているようです。

これにより、サービスの解決時に循環依存例外が発生します。

これは仕様によるものですか、それともバグですか?

4

3 に答える 3

11

V3 では、 の新しいオーバーロードBindという形で、これに対する解決策が最終的にあります。関連する質問を参照してください。


シングルトンを共有したい場合は、秒Bindを次のように変更する必要があります。

kernel.Bind<Service>().ToMethod(()=>kernel.Get<IService>()).InSingletonScope();

再循環参照や混乱など。内部的には、暗黙的な自己バインディングにより、サービスの暗黙的なバインディング登録が追加されます。例外を投稿する必要があります。

編集:あなたのコメントを再。次のようにすると:

Func<Service> serviceCreator = () => new Service(false);
kernel.Bind<Service>().ToMethod(serviceCreator).InSingletonScope();
kernel.Bind<IService>().ToMethod(()=>kernel.Get<Service>()).InSingletonScope();

IService次に、 Resolved 時に暗黙的な Class Self Binding は生成されません。既存のものを使用します。

ここ数週間、SO で別の Q がありましたが、誰かがこの種のことを行っていましたが、IInitializable で問題が発生していました。暗黙的なクラスの自己バインディングを生成します。

于 2010-06-30T10:02:28.370 に答える
6

ちなみに、Ninject3では次の構文を使用できます

kernel.Bind<IService, Service>().ToMethod(serviceCreator).InSingletonScope();

または、同様に:

kernel.Bind(typeof(IService), typeof(Service)).ToMethod(serviceCreator).InSingletonScope();

この後者のアプローチは、多くのサービスがある場合、または実行時にサービスを動的に検出した場合に適しています(params-style引数を配列として直接渡すことができます)。

于 2012-08-07T22:08:07.267 に答える
4

プロジェクトではRubenの方法を使用しましたが、バインディングでカーネルに戻る理由が直感的ではないことがわかりました。これを実行できるように、拡張メソッドとヘルパークラス(以下)を作成しました。

kernel.Bind<IService>().ToExisting().Singleton<Service>();

それは私にとってその意図をより明確に表現しているように見えました。

public static class DIExtensions
{
    public static ToExistingSingletonSyntax<T> ToExisting<T>(this IBindingToSyntax<T> binding)
    {
        return new ToExistingSingletonSyntax<T>(binding);
    }
}

// Had to create this intermediate class because we have two type parameters -- the interface and the implementation,
// but we want the compiler to infer the interface type and we supply the implementation type.  C# can't do that.
public class ToExistingSingletonSyntax<T>
{
    internal ToExistingSingletonSyntax(IBindingToSyntax<T> binding)
    {
        _binding = binding;
    }

    public IBindingNamedWithOrOnSyntax<T> Singleton<TImplementation>() where TImplementation : T
    {
        return _binding.ToMethod(ctx => ctx.Kernel.Get<TImplementation>()).InSingletonScope();
    }


    private IBindingToSyntax<T> _binding;
}
于 2011-03-04T15:34:36.787 に答える