You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Castle Windsor如何注册同一泛型接口的多个泛型实现类

问题场景

现有如下泛型接口与实现定义:

public interface IFileHandler<TLocation,TRow> { ... }

// 按RowTypeA定义的记录格式加载指定位置的文件
// 示例:RowTypeA类型的记录存储在匹配字符串'file_a.csv'的文件中
public class FileHandlerA<TLocation> : IFileHandler<TLocation, RowTypeA>{ ... }

// 按RowTypeB定义的记录格式加载指定位置的文件
// 示例:RowTypeB类型的记录存储在匹配字符串'file_b.csv'的文件中
public class FileHandlerB<TLocation> : IFileHandler<TLocation, RowTypeB>{ ... }

public class MyCode {
    ...
    public void MyMethod()
    {
       // 期望的解析效果
        var fh1 = container.Resolve<IFileHandler<Location1, RowTypeA>>(); // 得到FileHandlerA<Location1>实例
        var fh2 = container.Resolve<IFileHandler<Location2, RowTypeA>>(); // 得到FileHandlerA<Location2>实例
        var fh3 = container.Resolve<IFileHandler<Location1, RowTypeB>>(); // 得到FileHandlerB<Location1>实例
    }
    ... 
 }
已尝试的注册方案

你之前尝试的两种注册思路方向都是正确的,只需要做少量调整即可生效:

// 扫描注册的写法存在语法缺漏
 Classes
     .FromAssembly(thisAssembly)
     .BasedOn(typeof(IFileHandler<,>) // 缺了右括号
     .WithServiceAllInterfaces();

// 开放泛型注册不知道怎么传实现类
Component
  .For<IFileHandler<,>>()
  .ImplementedBy<???>

Castle Windsor 正确注册方案

因为你的FileHandlerA<>/FileHandlerB<>属于半封闭泛型实现(已经固定了TRow泛型参数,仅保留TLocation作为开放参数),Castle Windsor原生支持这类泛型的自动匹配解析,两种注册方式调整后如下:

方案1:显式注册开放泛型实现

直接逐个注册对应行类型的半开放泛型实现即可,Windsor会在解析时自动填充TLocation参数:

container.Register(
    // 注册RowTypeA对应的处理器
    Component.For(typeof(IFileHandler<,>))
             .ImplementedBy(typeof(FileHandlerA<>))
             .LifestyleTransient(),
    // 注册RowTypeB对应的处理器
    Component.For(typeof(IFileHandler<,>))
             .ImplementedBy(typeof(FileHandlerB<>))
             .LifestyleTransient()
);

方案2:修正后的程序集扫描注册

补全语法,并且指定用基接口作为服务暴露即可:

container.Register(
    Classes.FromAssembly(thisAssembly)
           .BasedOn(typeof(IFileHandler<,>)) // 补全右括号
           .WithService.Base() // 只绑定IFileHandler<,>接口,比WithServiceAllInterfaces更精准
           .LifestyleTransient()
);

更优的设计方案

如果后续行类型会持续新增,每次新增RowType都要加对应的FileHandlerX实现会产生大量重复代码,可以把行类型和文件的匹配规则抽离,用统一的泛型实现:

  1. 先给行类型加匹配规则特性
[AttributeUsage(AttributeTargets.Class)]
public class FilePatternAttribute : Attribute
{
    public string Pattern { get; }
    public FilePatternAttribute(string pattern) => Pattern = pattern;
}

[FilePattern("file_a.csv")]
public class RowTypeA { }

[FilePattern("file_b.csv")]
public class RowTypeB { }
  1. 实现通用泛型处理器
public class FileHandler<TLocation, TRow> : IFileHandler<TLocation, TRow>
{
    public FileHandler()
    {
        // 从行类型特性中自动读取匹配规则
        var filePattern = typeof(TRow).GetCustomAttribute<FilePatternAttribute>()?.Pattern;
        // 原有加载逻辑
    }
}
  1. 仅需注册一次开放泛型即可
container.Register(
    Component.For(typeof(IFileHandler<,>))
             .ImplementedBy(typeof(FileHandler<,>))
             .LifestyleTransient()
);

后续新增行类型只需定义RowType类加FilePattern特性即可,不需要新增处理器实现,扩展性更强。


内容的提问来源于stack exchange,提问作者Denis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:36:03