1

我有以下课程:

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-open-generic,以处理对类型服务的任何请求 IDbCommandHandler<SubIdentifierItemCreateCommand<,>,>

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

_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>>();
4

1 回答 1

0

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

解决方案很简单,迁移到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);
        }
    }
};

我知道,这很丑陋,但至少有一个解决方法;-)

于 2013-02-22T02:43:17.337 回答