3

私は.NET 4.5、Ninject 3を次のように慣例libによるバインディングで使用しています:

kernel.Bind(x => x
    .FromAssembliesMatching("assembly.dll")
    .SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>))
    .BindAllInterfaces());

そして、これは次の場合に適切にバインドされます:

public class MyCommandHandler : ICommandHandler<MyCommand>

しかし、バインドしません:

public class MyGenericCommandHandler<T> : ICommandHandler<MyGenericCommand<T>>

ただし、次のようなジェネリック クラスの特定の実装に個別のバインディングを追加すると、前のバインディングが機能します。

kernel.Bind(typeof(ICommandHandler<MyGenericCommand<float>>))
      .To(typeof(MyGenericCommandHandler<float>))
kernel.Bind(typeof(ICommandHandler<MyGenericCommand<int>>))
      .To(typeof(MyGenericCommandHandler<int>))

ただし、個々のジェネリック型をそれぞれ追加すると、規則の目的が無効になり、float、int、string などの可能な個々の型ごとにバインディングを追加する必要があります...

私のコマンドの汎用バージョンをサポートするために、規則を変更する方法、または別の規則を追加する方法 (またはまったく異なるソリューションを使用する方法) を知っていますか? つまり、2 レベルのジェネリックをサポートします。

4

1 に答える 1

0

EDIT:コンパイルされません[そして、要件が意味をなさないことを明らかにしていないという事実]、コメントでこの結論の理由を参照してください。


これは、通常のオープン ジェネリック ケースです。私の以前のコメントのリンクでほのめかされたように、DRY を作成するための基本的なバインドの方法は次のとおりです。

kernel.Bind(typeof(ICommandHandler<MyGenericCommand<>>))
    .To(typeof(MyGenericCommandHandler<>));

このバインディングは、 の任意のTバリアントに対して十分ですICommandHandler<MyGenericCommand<T>>

コンベンションベースのバインディングを期待どおりのマッピングに行うという文脈では、問題はSelectAllClasses().InheritedFrom(typeof(ICommandHandler<>))ジェネリッククラスが含まれていないことです。これは、非具象クラスで一般化されたルールを指定できることはめったにないため、理にかなっています。

次のいずれかを実行できます

  • DSL の別の Projection 部分を使用して Generic クラスを選択し、何らかの規約に基づいた方法でそれらをバインドします。
  • NinjectModule上記を実行する [open] 汎用サービスを公開するアセンブリからaを公開しBind、次にkernel.Load()モジュールの a を実行します [DLL 名パターンによるプローブ]。
于 2013-05-27T14:51:15.410 に答える