2016-11-13 14 views
0

MediatrとAutofacでメディエータのパイプラインを構築しようとしていますが、Autofacからバリデータのコレクションを解決しようとしています。AutofacでIEnumerableを解決する

public class MediatorPipeline<TRequest, TResponse> 
    : IAsyncRequestHandler<TRequest, TResponse> where TRequest : IAsyncRequest<TResponse> 
{ 
    private readonly IAsyncRequestHandler<TRequest, TResponse> _inner; 
    private readonly IEnumerable<IValidator<TRequest>> _validators; 

    public MediatorPipeline(IAsyncRequestHandler<TRequest, TResponse> inner, 
     IEnumerable<IValidator<TRequest>> validators) 
    { 
     _inner = inner; 
     _validators = validators; 
    } 
    ... 
} 

私はコンストラクタでIValidator<TRequest>を入れるとそれがうまく解決されますが、私はIEnumerable<IValidator<TRequest>>を入れたときに、それが失敗し、例外:

コンテナまたはサービスロケータ適切に設定されていないか、ハンドラあなたのコンテナに登録されていません。 ---> Autofac.Core.DependencyResolutionException:特定の登録のアクティブ化中にエラーが発生しました。ここで

私の登録コードです:

builder.RegisterAssemblyTypes(assembly) 
    .Where(t => t.IsClosedTypeOf(typeof(IValidator<>))) 
    .AsImplementedInterfaces() 
    .InstancePerLifetimeScope(); 

私はこの代替の登録と同じ結果だった:感謝

var openGenericType = typeof(IValidator<>); 

var query = from type in assembly.GetTypes().Where(c => !(c.GetTypeInfo().IsAbstract || c.GetTypeInfo().IsGenericTypeDefinition)) 
      let interfaces = type.GetInterfaces() 
      let genericInterfaces = interfaces.Where(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition() == openGenericType) 
      let matchingInterface = genericInterfaces.FirstOrDefault() 
      where matchingInterface != null 
      select new { matchingInterface, type }; 

foreach (var pair in query) 
{ 
    builder.RegisterType(pair.type).As(pair.matchingInterface); 
} 

任意の提案を!

+0

は、あなたのフィルタリングロジックは、実際にあなたが期待する型を返すことを確認するためにチェックしましたか? 2番目の方法では、foreachループが実際に期待しているすべての型を処理することをデバッグして確認できます。 問題はAutofac登録ではなく、タイプクエリであることを確認してください。 –

答えて

0

最初に、内部例外が含まれていることをスタックトレースで確認するとよいでしょう。

Autofacは、あなたがこの方法を使用することができる便利な拡張メソッド、AsClosedTypesOfを公開:

builder 
    .RegisterAssemblyTypes(ThisAssembly) 
    .AsClosedTypesOf(typeof(IValidator<>)) 
    .InstancePerLifetimeScope(); 

あなたのバリデータを登録するために、深い反射に行く必要はありませんので、これはあなたのための作業を行います。あなたは、それらの上にあなたのハンドラやデコレータを登録する必要があり

builder 
    .RegisterAssemblyTypes(ThisAssembly) 
    .AsClosedTypesOf(typeof(IAsyncRequestHandler<,>), "base-handler") 
    .InstancePerDependency(); 

builder.RegisterGenericDecorator(
    typeof(MediatorPipeline<,>), 
    typeof(IAsyncRequestHandler<,>), 
    "base-handler"); 
関連する問題