Castle Windsor自动解析通用接口工作不正常

时间:2013-04-30 16:34:26

标签: c# asp.net-mvc dependency-injection castle-windsor

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

我映射了entites代码:

container.RegisterServices(
    Assembly.GetAssembly(typeof(GridEntityService<,>))); 

我有两个泛型的接口:

IGridEntityService<TEntity,TService>

我有两个这个接口的实现。第一:

GridEntityService<TEntity,TService>: IGridEntityService<TEntity,TService>

我也有自定义实现。第二:

TaskServiceOne : GridEntityService<User, LoginService> { }
TaskServiceTwo : GridEntityService<Report, LoginService> { }

在我的控制器构造函数中:

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
}

我怎么能对温莎城堡说正确的?为什么他们弄错了?我有其他地方,我有类似的服务,他们工作正常。

编辑。 Anwser发表评论。你是对的。它的扩展方法是:

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

3 个答案:

答案 0 :(得分:3)

问题是,温莎将选择一种更具体的类型,而不是特定类型。这就是为什么,如果你有组件/服务对:

TaskServiceTwo / IGridEntityService<Report, LoginService>
GridEntityService<, > / IGridEntityService<, >

默认情况下会选择第一个组件,因为它比第二个组件更具体。

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

如果您不希望它满足此服务,您为什么会TaskServiceTwo曝光IGridEntityService<Report, LoginService>

也许它的注册应该被修改,或者它根本不应该注册?

如果你想保留它(可能还有一些其他组件依赖它),只需覆盖这个特定情况的默认值......好吧,你可以。

注册UserController时,您应将其配置为依赖GridEntityService<, >The documentation shows you all the options for doing that

答案 1 :(得分:1)

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

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<,>)))

答案 2 :(得分:0)

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