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

本文关键字:接口 工作 不正确 Winsdor Castle | 更新日期: 2023-09-27 18:11:28

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

I映射实体代码:

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
}

我怎么说温莎城堡得到正确的一个?为什么会出错呢?我在其他地方也有类似的服务,而且运行得很好。

编辑。回复评论。你说得对。它的扩展方法:

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

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

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

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

它将默认选择第一个组件,因为它比第二个组件更具体。

正确的方法是不同的应用程序

如果您不希望它满足此服务,为什么您甚至让TaskServiceTwo暴露IGridEntityService<Report, LoginService> ?

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

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

注册UserController时,您应该将其配置为依赖于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<,>)))

问题是兑现服务程序集。它在bin文件夹里。它使用旧代码,其中没有实现TaskServiceTwo。我清除了解决方案并手动删除了Service.dll。它在不更改代码的情况下修复了这个问题。