我们说我有这堂课:
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 :(得分: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
。