C# Castle Winsdor自动解析通用接口工作不正确

C# Castle Winsdor自动解析通用接口工作不正确,c#,asp.net-mvc,dependency-injection,castle-windsor,C#,Asp.net Mvc,Dependency Injection,Castle Windsor,我使用Castle Winsdor作为DI解析工具 I地图实体代码: container.RegisterServices( Assembly.GetAssembly(typeof(GridEntityService<,>))); container.RegisterServices( GetAssembly(typeof(GridEntityService)); 我有两个泛型接口: IGridEntityService<TEntity,TService>

我使用Castle Winsdor作为DI解析工具

I地图实体代码:

container.RegisterServices(
    Assembly.GetAssembly(typeof(GridEntityService<,>))); 
container.RegisterServices(
GetAssembly(typeof(GridEntityService));
我有两个泛型接口:

IGridEntityService<TEntity,TService>
IGridEntityService
我有两个接口的实现。第一:

GridEntityService<TEntity,TService>: IGridEntityService<TEntity,TService>
GridEntityService:IGridEntityService
而且我还有自定义实现。第二:

TaskServiceOne : GridEntityService<User, LoginService> { }
TaskServiceTwo : GridEntityService<Report, LoginService> { }
TaskServiceOne:GridEntityService{}
TaskServiceTwo:GridEntityService{}
在我的控制器构造函数中:

public UserController(
    IGridEntityService<User, LoginService> userService,
    IGridEntityService<Report, LoginService> reportService)
{
    // Get Correct one TaskServiceOne
    GridEntityService = userService;
    // Get GridEntityService<Report, LoginService> 
    // not the TaskServiceTwo
    GridSecondEntityService = reportService
}
公共用户控制器(
IGridEntityService用户服务,
IGridEntityService报告服务)
{
//获取正确的一个TaskServiceOne
GridEntityService=userService;
//获取GridEntityService
//不是第二个
GridSecondEntityService=reportService
}
我该怎么跟温莎城堡说才能得到正确的答案?为什么他们会变得不正确?我有其他地方,在那里我有类似的服务,他们工作得很好

编辑。 安沃斯对此发表评论。你是对的。它的扩展方法是:

 public static void RegisterServices(this IWindsorContainer container, Assembly assembly)
            {
                container.Register(
                    AllTypes.FromAssembly(assembly).Where(t => true).WithService.AllInterfaces().Configure(
                        reg => reg.LifeStyle.Custom<InstantiateAndForgetIt>()));
            }
publicstaticvoidregisterservices(此IWindsorContainer容器,程序集)
{
集装箱。登记(
AllTypes.FromAssembly(assembly).Where(t=>true).WithService.AllInterfaces().Configure(
reg=>reg.lifety.Custom());
}

也许有一种更简单的方法,但据我所知,您必须显式映射开放泛型类型,如下所示:

container.Register(AllTypes.From( 
    AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetExportedTypes()))
    .BasedOn(typeof(IGridEntityService<,>))
    .Unless(t => t.IsGenericTypeDefinition)
    .WithService.Select((_, baseTypes) =>
    { 
        return 
            from t in baseTypes
            where t.IsGenericType
            let td = t.GetGenericTypeDefinition()
            where td == typeof(IGridEntityService<,>)
            select t;
    })
    .Configure(c => c.LifeStyle.Transient));


container.Register(Component
    .For(typeof(IGridEntityService<,>))
    .ImplementedBy(typeof(GridEntityService<,>)))
container.Register(AllTypes.From(
AppDomain.CurrentDomain.GetAssemblys()
.SelectMany(a=>a.GetExportedTypes())
.BasedOn(类型(IGridEntityService))
.除非(t=>t.IsGenericTypeDefinition)
.WithService.Select((ux,baseTypes)=>
{ 
返回
从基类中的t开始
其中t.IsGenericType
设td=t.GetGenericTypeDefinition()
其中td==typeof(IGridEntityService)
选择t;
})
.Configure(c=>c.lifesture.Transient));
容器寄存器(组件
.For(类型(IGridEntityService))
.ImplementedBy(typeof(GridEntityService)))

也许有一种更简单的方法,但据我所知,您必须显式映射开放泛型类型,如下所示:

container.Register(AllTypes.From( 
    AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetExportedTypes()))
    .BasedOn(typeof(IGridEntityService<,>))
    .Unless(t => t.IsGenericTypeDefinition)
    .WithService.Select((_, baseTypes) =>
    { 
        return 
            from t in baseTypes
            where t.IsGenericType
            let td = t.GetGenericTypeDefinition()
            where td == typeof(IGridEntityService<,>)
            select t;
    })
    .Configure(c => c.LifeStyle.Transient));


container.Register(Component
    .For(typeof(IGridEntityService<,>))
    .ImplementedBy(typeof(GridEntityService<,>)))
container.Register(AllTypes.From(
AppDomain.CurrentDomain.GetAssemblys()
.SelectMany(a=>a.GetExportedTypes())
.BasedOn(类型(IGridEntityService))
.除非(t=>t.IsGenericTypeDefinition)
.WithService.Select((ux,baseTypes)=>
{ 
返回
从基类中的t开始
其中t.IsGenericType
设td=t.GetGenericTypeDefinition()
其中td==typeof(IGridEntityService)
选择t;
})
.Configure(c=>c.lifesture.Transient));
容器寄存器(组件
.For(类型(IGridEntityService))
.ImplementedBy(typeof(GridEntityService)))

问题是,温莎会选择更具体的类型,而不是不太具体的类型。这就是为什么,如果您有组件/服务对:

TaskServiceTwo / IGridEntityService<Report, LoginService>
GridEntityService<, > / IGridEntityService<, >
TaskServiceTwo/IGridEntityService
GridEntityService/IGridEntityService
默认情况下,它将拾取第一个零部件,因为它比第二个零部件更具体

现在,正确的解决方法因应用程序而异

如果您不希望TaskServiceTwo满足此项服务,那么为什么还要使用
TaskServiceTwo
公开
IGridEntityService

也许它的注册应该更改,或者根本不应该注册

如果您确实希望保留它(可能其他一些组件依赖于它),并且只覆盖此特定情况的默认值。。。嗯,你可以


注册
UserController
时,应将其配置为依赖
GridEntityService

问题是,温莎会选择更具体的类型,而不是不太具体的类型。这就是为什么,如果您有组件/服务对:

TaskServiceTwo / IGridEntityService<Report, LoginService>
GridEntityService<, > / IGridEntityService<, >
TaskServiceTwo/IGridEntityService
GridEntityService/IGridEntityService
默认情况下,它将拾取第一个零部件,因为它比第二个零部件更具体

现在,正确的解决方法因应用程序而异

如果您不希望TaskServiceTwo满足此项服务,那么为什么还要使用
TaskServiceTwo
公开
IGridEntityService

也许它的注册应该更改,或者根本不应该注册

如果您确实希望保留它(可能其他一些组件依赖于它),并且只覆盖此特定情况的默认值。。。嗯,你可以


注册
UserController
时,应将其配置为依赖
GridEntityService

问题是在服务组装时兑现的。它在bin文件夹中。它采用旧代码,其中没有TaskServiceTwo的实现。我清除了解决方案并手动删除了Service.dll。它在不更改代码的情况下解决了问题

问题是在服务组装时兑现的。它在bin文件夹中。它采用旧代码,其中没有TaskServiceTwo的实现。我清除了解决方案并手动删除了Service.dll。它在不更改代码的情况下解决了问题

您使用的是什么温莎版本。我似乎没有容器。RegisterServices。您使用的是哪个温莎版本。我好像没有容器。RegisterServices。谢谢您抽出时间。我想买两个。我发现这个问题是有争议的。那不是城堡里的温斯多虫。是VS2012 bug让我发疯了。它将服务assambly兑现并放入Bin文件夹。所以无论我做什么,都会给我旧版本的代码。今天,我清除了解决方案并手动删除服务箱,所有服务都开始正常工作。非常感谢你的帮助,谢谢你抽出时间。我想买两个。我哈