2016-09-28 17 views
1

だが、私はこのクラスを持っているとしましょう:登録ジェネリック型

public class DetailedQueryHandler<T> : IQueryHandlerAsync<Detailed, T> 
    where T : CalculationQuery 

私はそのようにそれを登録することができます

builder.RegisterType(typeof(DetailedQueryHandler<CalculationWithDealerQuery>)) 
     .As(typeof(IQueryHandlerAsync<Detailed, CalculationWithDealerQuery>)); 
builder.RegisterType(typeof(DetailedQueryHandler<CalculationQuery>)) 
     .As(typeof(IQueryHandlerAsync<Detailed, CalculationQuery>)); 

しかし、私は、私は登録することができますように、より自動化方法でそれを登録したいです

var types = ThisAssembly.GetTypes(); 
builder.RegisterTypes(types) 
     .Where(t => t.ImplementGenericInterface(t2 => t2 == typeof(IQueryHandlerAsync<,>)) 
     .AsImplementedInterfaces() 

:以下IQueryHandlerAsyncインターフェイスへのタイプ210
public interface IQueryHandlerAsync<T, in TI> 

public static bool ImplementGenericInterface(this Type type, Func<Type, bool> comparer) { 
     return type.GetInterfaces().Any(i => i.IsGenericType 
      && comparer(i.GetGenericTypeDefinition())); 
} 

これを解決するにはどうすればよいでしょうか?

答えて

0

具体的なIQueryHandlerAsyncの実装を特定のCalculationQueryに関連付ける方法が必要です。

これを行うための1つの可能な方法は、あなたが望むタイプを登録し、あなたのための登録を行うにはAsQueryHandlerメソッドを作成することです:

public static class ContainerBuilderExtensions 
{ 
    public static IRegistrationBuilder<TLimit, TConcreteActivatorData, SingleRegistrationStyle> AsQueryHandler<TLimit, TConcreteActivatorData>(this IRegistrationBuilder<TLimit, TConcreteActivatorData, SingleRegistrationStyle> registration) 
     where TConcreteActivatorData : IConcreteActivatorData 

    { 
     Type queryHandlerType = registration.ActivatorData.Activator.LimitType; 
     Type queryHandlerRegistrationType = queryHandlerType.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IQueryHandlerAsync<,>)); 
     if (queryHandlerRegistrationType == null) 
     { 
      throw new ArgumentException($"{queryHandlerType} doesn't implement {typeof(IQueryHandlerAsync<,>).Name} interface"); 
     } 
     TypedService queryHandlerService = new TypedService(queryHandlerRegistrationType); 

     return registration.As(queryHandlerService); 
    } 
} 

そして、あなたはこのようにそれを使用します。

builder.RegisterType<DetailedQueryHandler<CalculationQuery>>() 
     .AsQueryHandler(); 

すべてのタイプを手動で登録したくない場合は、必要に応じてタイプを組み立てるためにアセンブリスキャンを実行する必要があります。

もう1つの方法は、IRegistrationSourceインターフェイスを実装することです。このインターフェイスには、Autofacに新しいコンポーネントが必要なときに呼び出されるRegistrationsForメソッドが含まれています。このインターフェイスは、要求に応じてコンポーネントを動的に登録する手段として見ることができます。

builder.RegisterSource(new QueryHandlerRegistrationSource()); 

代わりのif (t0 == typeof(Detailed))あなたがQueryHandlerRegistrationSourceのパラメータとしてIDictionary<Type, Type>を使用することができます。

public class QueryHandlerRegistrationSource : IRegistrationSource 
{ 
    public Boolean IsAdapterForIndividualComponents 
    { 
     get 
     { 
      return false; 
     } 
    } 

    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) 
    { 
     Type serviceType = (service as IServiceWithType)?.ServiceType; 

     if (serviceType == null) 
     { 
      yield break; 
     } 
     if (serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(IQueryHandlerAsync<,>)) 
     { 
      Type[] argumentTypes = serviceType.GetGenericArguments(); 
      Type t0 = argumentTypes[0]; 
      Type t1 = argumentTypes[1]; 

      if (t0 == typeof(Detailed)) 
      { 
       IComponentRegistration registration = RegistrationBuilder.ForType(typeof(DetailedQueryHandler<>).MakeGenericType(t1)) 
                     .As(service) 
                     .CreateRegistration(); 
       yield return registration; 
      } 
      else 
      { 
       throw new NotSupportedException(); 
      } 
     } 

    } 
} 

は、登録ソースを登録することを忘れないでください。

関連する問題