2016-09-28 106 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>)); 

但我想更自动化的方式来注册它,就像我可以注册类型下面IQueryHandlerAsync接口:

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

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关联。

一种可能的方式做,这就是注册你想要的类型,并创建一个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(); 

如果您不想手动注册所有类型,则必须根据您的需要进行程序集扫描以组合所需的类型。

另一种考虑的方法是实现接口IRegistrationSource。该界面包含一个RegistrationsFor方法,当Autofac需要一个新组件时将调用该方法。您可以将此界面视为根据需求动态注册组件的一种方式。

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(); 
      } 
     } 

    } 
} 

不要忘记注册登记来源:

builder.RegisterSource(new QueryHandlerRegistrationSource()); 

取而代之的if (t0 == typeof(Detailed))您可以使用IDictionary<Type, Type>QueryHandlerRegistrationSource的参数。