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タイプのサービスのリクエストを処理するには、シングルトンオープンジェネリックとして 登録する必要があります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」制約を正しく処理しません。

解決策は単純です。SimpleInjector2.0に移行しますNuGet経由)。

何らかの理由でSimpleInjector2.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 に答える