2

StructureMap内部型を指定したり、型固有のインターフェイスを作成したりせずに、ネストされたジェネリックを接続する方法があるかどうか疑問に思っています。これは少し紛らわしいので、コーディング例は、探している機能のより良い説明になるかもしれません。

public interface IParser<T> { }
public class Range<T> where T : struct { }
public class RangeParser<T> : IParser<Range<T>> { }

理論的には、次のような StructureMap のオープン ジェネリック機能を使用できるようにしたいと考えています。

For(typeof(IRepository<>)).Use(typeof(Repository<>)).

私はこれを行うことができないことに気づきました:

For(typeof(IParser<Range<>>).Use(typeof(RangeParser<>));

リフレクションを介して実行しようとしましたがMakeGenericType、そのアプローチで問題が発生しているようです。

var requestedType = typeof(IParser<>).MakeGenericType(typeof(Range<>));
For(requestedType).Use(typeof(RangeParser<>));

どんなアイデアでも大歓迎です。

4

1 に答える 1

2

オープン ジェネリックのサポートに関しては、StructureMap はかなり制限されています。一方、 Simple Injectorを使用すると、次のことができます。

// using SimpleInjector.Extensions;

container.RegisterOpenGeneric(typeof(IParser<>), typeof(RangeParser<>));

これは、がどこにあるかにマップIParser<Range<T>>されます。複数の一般的な実装がある場合は、単純に追加の実装を追加できます。RangeParser<T>TstructIParser<T>

container.RegisterOpenGeneric(typeof(IParser<>), typeof(RangeParser<>));
container.RegisterOpenGeneric(typeof(IParser<>), typeof(ReferenceTypeParser<>));

確認する必要があるのは、登録が重複していないことだけです。IParser<T>複数の登録で処理できる閉じた型を解決 (または注入) しようとすると、Simple Injector は例外をスローします。

オーバーラップがある場合は、次のRegisterOpenGenericようにメソッドに述語を指定できます。

container.RegisterOpenGeneric(typeof(IParser<>), typeof(RestrictiveParser<>));
container.RegisterOpenGeneric(typeof(IParser<>), typeof(FallbackParser<>), 
    c => !c.Handled);

これらの登録は、登録順に評価されます。

ジェネリック型の制約を自然なフィルターとして使用でき、Simple Injector はそれらに従います。ジェネリック型の制約がそれをカットしない場合は、いつでも部分的なオープン ジェネリック型を登録できます。

container.RegisterOpenGeneric(typeof(IParser<>), 
    typeof(SomeParser<>).MakeGenericType(typeof(List<>));

.NET 用のすべての IoC フレームワークの中で、Simple Injector はジェネリック型付けを最もよくサポートしています。

  • ジェネリック型の制約を理解しています。
  • 複雑なネストされたジェネリック型のマッピングが可能です。
  • 部分的なオープン ジェネリック型を提供できます。
  • 型に汎用デコレータを適用できます。
  • ジェネリック型の制約に基づいて、ジェネリック デコレータを条件付きで適用できます。
  • これにより、非ジェネリック実装と、提供されたオープン ジェネリック型の自動決定されたクローズド バージョンが混在するコレクションを登録できます。
于 2013-09-25T18:33:29.103 に答える