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

C# 10 如何避免类型切换为不同IResponse子类型匹配对应评估器

解决方案

针对你的需求,推荐优先使用类型映射+非泛型评估器包装的实现方案,完全符合开闭原则,不需要每次新增答复类型修改原有聚合器代码,C# 10 原生支持,改动成本极低。

实现步骤

1. 新增非泛型评估器统一入口

定义非泛型基础评估器接口,用来抹平不同泛型评估器的类型差异:

public interface IResponseEvaluator
{
    decimal Evaluate(object response);
    bool CanEvaluate(Type responseType);
}

让原有泛型IResponseEvaluator继承该接口,用显式接口实现封装内部逻辑,不对外暴露非泛型方法:

interface IResponseEvaluator<TQuestion, TResponse> : IResponseEvaluator
    where TQuestion : Question
    where TResponse : IResponse<TQuestion>
{
    decimal Evaluate(TResponse response);
    
    // 显式实现非泛型接口,仅内部调用
    decimal IResponseEvaluator.Evaluate(object response) => Evaluate((TResponse)response);
    bool IResponseEvaluator.CanEvaluate(Type responseType) => typeof(TResponse).IsAssignableFrom(responseType);
}

2. 重构EvaluationAggregator

删除原有零散的评估器属性,改为统一存储所有注册的评估器,动态匹配对应类型:

class EvaluationAggregator
{
    private readonly List<IResponseEvaluator> _registeredEvaluators = new();
    
    // 供构建器调用的评估器注册方法
    internal void RegisterEvaluator(IResponseEvaluator evaluator) 
        => _registeredEvaluators.Add(evaluator);
    
    public decimal EvaluateAll(IEnumerable<IResponse<Question>> responses)
    {
         decimal totalScore = 0;
         foreach (var response in responses)
         {
              var evaluator = _registeredEvaluators.FirstOrDefault(e => e.CanEvaluate(response.GetType()));
              if (evaluator == null)
              {
                  // 可根据业务需求自定义未匹配到评估器的逻辑
                  throw new NotSupportedException($"未找到响应类型 {response.GetType().Name} 对应的评估器");
              }
              totalScore += evaluator.Evaluate(response);
         }    
         return totalScore;
    }
}

3. 优化构建器实现

新增通用的评估器注册方法,兼容原有调用习惯的同时支持扩展:

class EvaluationAggregatorBuilder
{
    private readonly EvaluationAggregator _aggregator = new();
    
    // 通用注册方法,新增类型时直接调用即可
    public EvaluationAggregatorBuilder AddEvaluator<TQuestion, TResponse>(IResponseEvaluator<TQuestion, TResponse> evaluator)
        where TQuestion : Question
        where TResponse : IResponse<TQuestion>
    {
        _aggregator.RegisterEvaluator(evaluator);
        return this;
    }
    
    // 保留原有强类型注册方法,兼容旧代码
    public EvaluationAggregatorBuilder UseChoiceEvaluator(DefaultMultipleChoiceResponseEvaluator evaluator)
        => AddEvaluator<MultipleChoiceQuestion, MultipleChoiceResponse>(evaluator);
    
    public EvaluationAggregatorBuilder UseTextEvaluator(DefaultTextResponseEvaluator evaluator)
        => AddEvaluator<TextQuestion, TextResponse>(evaluator);
    
    public EvaluationAggregator Build() => _aggregator;
}

扩展规则

后续新增答复类型时,仅需要做3件事,不需要修改任何原有逻辑:

  • 新增对应IResponse<新Question类型>的实现类
  • 新增对应IResponseEvaluator<新Question类型, 新Response类型>的实现类
  • 在构建器调用AddEvaluator方法注册新的评估器即可

轻量替代方案(仅推荐小体量项目使用)

如果追求代码极简,可直接用dynamic动态派发实现,不需要修改原有评估器接口,仅需修改聚合器和构建器:

class EvaluationAggregator
{
    private readonly Dictionary<Type, dynamic> _evaluatorMap = new();
    
    internal void RegisterEvaluator(Type responseType, dynamic evaluator) 
        => _evaluatorMap[responseType] = evaluator;
    
    public decimal EvaluateAll(IEnumerable<IResponse<Question>> responses)
    {
         decimal totalScore = 0;
         foreach (var response in responses)
         {
              if (!_evaluatorMap.TryGetValue(response.GetType(), out var evaluator))
              {
                  throw new NotSupportedException($"未找到响应类型 {response.GetType().Name} 对应的评估器");
              }
              totalScore += evaluator.Evaluate((dynamic)response);
         }    
         return totalScore;
    }
}

该方案牺牲了部分类型安全性和性能,代码量减少30%左右,适合响应类型数量少于10个的小型项目。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:36:02