我使用了 Matt Davies 回答中的代码并对其进行了一些改进:
- 它现在可以正确处理实现其他接口的命令处理程序。
- 它现在可以正确处理
ICommandHandler<T>
多次实现的命令处理程序。
- 我通过将第一个参数固定为
WithParameter
. 像这样它现在支持多个构造函数参数FactoryCommandHandler<T>
。
结果如下所示:
public static class AutofacExtensions
{
public static void RegisterGenericTypesWithFactoryDecorator(
this ContainerBuilder builder,
IEnumerable<Type> relevantTypes,
Type factoryDecorator,
Type implementedInterfaceGenericTypeDefinition)
{
var serviceName = implementedInterfaceGenericTypeDefinition.ToString();
foreach (var implementationType in relevantTypes)
{
var implementedInterfaces =
implementationType.GetGenericInterfaces(
implementedInterfaceGenericTypeDefinition);
foreach (var implementedInterface in implementedInterfaces)
builder.RegisterType(implementationType)
.Named(serviceName, implementedInterface);
}
builder.RegisterGeneric(factoryDecorator)
.WithParameter(
(p, c) => IsSpecificFactoryParameter(p, implementedInterfaceGenericTypeDefinition),
(p, c) => c.ResolveNamed(serviceName, p.ParameterType))
.As(implementedInterfaceGenericTypeDefinition)
.SingleInstance();
}
private static bool IsSpecificFactoryParameter(ParameterInfo p,
Type expectedFactoryResult)
{
var parameterType = p.ParameterType;
if (!parameterType.IsGenericType ||
parameterType.GetGenericTypeDefinition() != typeof(Func<>))
return false;
var actualFactoryResult = p.ParameterType.GetGenericArguments()
.First();
if (actualFactoryResult == expectedFactoryResult)
return true;
if (expectedFactoryResult.IsGenericTypeDefinition &&
actualFactoryResult.IsGenericType)
return expectedFactoryResult ==
actualFactoryResult.GetGenericTypeDefinition();
return false;
}
}
public static class TypeExtensions
{
public static IEnumerable<Type> GetGenericInterfaces(
this Type type, Type openGenericInterface)
{
return
type.GetInterfaces()
.Where(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == openGenericInterface);
}
}
用法:
var relevantTypes = assembly.GetTypes();
builder.RegisterGenericTypesWithFactoryDecorator(
relevantTypes.Where(type => type.Name.EndsWith("CommandHandler")),
typeof(FactoryCommandHandlerDecorator<>),
typeof(ICommandHandler<>));