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

我知道,這是醜陋的,但至少有一個工作;-)