1

我有以下类别:使用simpleinjector注册opengeneric

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为单-opengeneric,以处理 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>>(); 
+0

伟大的仿制药母亲!这是一些疯狂的屁股通用狗屎,你已经到了那里。请给我一点时间来解释你的问题。 – Steven 2013-02-21 22:38:00

回答

0

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

解决方法很简单,迁移到Simple Injector 2.0via NuGet)。

如果你什么都原因不能切换到简单的喷油器2.0,可以为类型的注册来解决这个bug在1.6.1版本注册ResolveUnregisteredType事件:

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

我知道,这是丑陋的,但至少有一个工作;-)