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

C#中编译期未知List对应字段名时如何正确调用AddRange方法

问题原因

一共有4处错误,分别对应从获取字段到调用方法的全流程:

  • 字段名生成错误:你调用selections[0].GetType().ToString()拿到的是类型的完整限定名(包含命名空间),比如Tree类如果在Game.Logic命名空间下,返回值是Game.Logic.Tree,转小写后拼接出来的字段名是game.logic.treeselections,完全匹配不到你定义的treeSelections字段。应该改用GetType().Name只取类名部分。
  • 获取AddRange方法的所属类型错误:field是FieldInfo类型的反射对象,你调用field.GetType()拿到的是FieldInfo类本身的类型,这个类根本没有定义AddRange方法,自然返回null。正确的做法是通过field.FieldType拿到字段声明的List<Tree>类型,再从中查找AddRange方法。
  • Invoke调用时传错了目标实例:AddRange是List实例的成员方法,Invoke的第一个参数需要是List对象本身,你直接传field(FieldInfo对象),即使拿到正确的方法也会调用失败。需要先用field.GetValue(this)从当前JobManager实例中取出存储的List对象作为调用目标。
  • 参数类型不兼容:你要调用的List<Tree>.AddRange接收的参数类型是IEnumerable<Tree>,但你传入的是List<Harvestable>,二者没有隐式转换关系,直接调用会抛出参数类型不匹配的异常,需要先把输入的集合转换为对应泛型类型的可枚举集合。
修复后可运行的代码
public void OnMarkHarvestableSignal(List<Harvestable> selections)
{
    // 改用Name属性只取类名,避免带命名空间
    string fieldName = selections[0].GetType()
                                    .Name
                                    .ToLower() + "Selections";
    FieldInfo field = this.GetType()
                          .GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

    if (field is null)
        throw new Exception($"Field {fieldName} not found");
    
    // 取出实际存储的List实例
    object targetList = field.GetValue(this);
    // 从List的类型中获取AddRange方法
    MethodInfo addMethod = field.FieldType.GetMethod("AddRange");
    // 把输入集合转换为List对应泛型的数组
    Type listElementType = field.FieldType.GetGenericArguments()[0];
    Array convertedElements = Array.CreateInstance(listElementType, selections.Count);
    selections.CopyTo((Harvestable[])convertedElements);
    
    // 调用AddRange
    addMethod.Invoke(targetList, new object[] { convertedElements });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:15:07