使用simpleinjector注册opengeneric

本文关键字:opengeneric 注册 simpleinjector 使用 | 更新日期: 2023-09-27 18:00:23

我有以下类:

public interface IDbCommandHandler<in TCommand, out TOutput> 
    where TCommand : IDbCommand 
{
    TOutput Handle(TCommand command);
}
public class SubIdentifierItemCreateCommand<TItemType, TDefaultValues> 
    : BaseDbCommand
    where TItemType: TDefaultValues
{
}
public class SubIdentifierItemCreateCommandHandler<TItemType, TDefaultValues>
    : BaseDbCommandHandler<SubIdentifierItemCreateCommand<TItemType, TDefaultValues>, TItemType>,
    IDbCommandHandler<SubIdentifierItemCreateCommand<TItemType, TDefaultValues>, TItemType>
    where TItemType: class, TDefaultValues, IItemForGenericItemByIdentifierRetriever , new()
{
}

我需要将SubIdentifierItemCreateCommandHandler注册为singleton开放泛型,以处理对类型为的服务的任何请求CCD_ 2。

这可能吗?我尝试过各种方法,但总是会出错。

_container.RegisterSingleOpenGeneric(
    typeof(IDbCommandHandler<,>),
    typeof(SubIdentifierItemCreateCommandHandler<,>));
_container.RegisterOpenGeneric(
    typeof(IDbCommandHandler<,>),
    typeof(SubIdentifierItemCreateCommandHandler<,>));
// this one is throws a compile-time error, that you cannot 
// use partial open types.
_container.RegisterManyForOpenGeneric(
    typeof(IDbCommandHandler<SubIdentifierItemCreateCommand<,>,>),
    typeof(SubIdentifierItemCreateCommandHandler<,>)); 

我希望能够拨打以下电话并工作:

var item = _container.GetInstance<
    IDbCommandHandler<
        SubIdentifierItemCreateCommand<
            SectionData, 
            ISectionDataDefaultValues>, 
        SectionData>>();

使用simpleinjector注册opengeneric

不幸的是,您在框架中偶然发现了一个错误。Simple Injector 1.6.1无法正确处理"where TItemType:TDefault Values"约束。

解决方案很简单,可以迁移到simple Injector 2.0(通过NuGet)。

如果出于某种原因无法切换到Simple Injector 2.0,则可以注册ResolveUnregisteredType事件来注册类型,以解决1.6.1版本中的错误:

container.ResolveUnregisteredType += (sender, e) =>
{
    var serviceType = e.UnregisteredServiceType;
    if (serviceType.IsGenericType &&
        serviceType.GetGenericTypeDefinition() == typeof(IDbCommandHandler<,>))
    {
        var commandArg = serviceType.GetGenericArguments()[0];
        var outputArg = serviceType.GetGenericArguments()[1];
        if (commandArg.IsGenericType &&
            commandArg.GetGenericTypeDefinition() == 
                typeof(SubIdentifierItemCreateCommand<,>))
        {
            var itemTypeArgument = commandArg.GetGenericArguments()[0];
            var defaultValuesArgument = commandArg.GetGenericArguments()[1];
            if (itemTypeArgument != outputArg)
            {
                return;
            }
            Type typeToRegister;
            try
            {
                typeToRegister =
                    typeof(SubIdentifierItemCreateCommandHandler<,>)
                    .MakeGenericType(itemTypeArgument.GetGenericArguments());
            }
            catch (ArgumentException)
            {
                // Thrown by MakeGenericType when the type constraints 
                // do not match. In this case, we don't have to register
                // anything and can bail out.
                return;
            }
            object singleInstance = container.GetInstance(typeToRegister);
            // Register the instance as singleton.
            e.Register(() => singleInstance);
        }
    }
};

我知道,这很难看,但至少还有一个工作要做;-)