繁体   English   中英

注册通用类型

[英]Register generic type

假设我有这个课程:

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

什么是解决它的好方法?

在理解您的代码时,您需要一种方法将特定的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()); 

您可以使用IDictionary<Type, Type>作为QueryHandlerRegistrationSource的参数,而不是if (t0 == typeof(Detailed))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM