如何从Condition<T>泛型对象列表中读取Value字段?
解决泛型Condition列表中访问Value字段的问题
你遇到的核心问题有两个:一是基接口ConditionBase没有暴露Value相关成员,编译时无法通过ConditionBase引用访问泛型类里的Value;二是原代码的类型判断逻辑有误——c.GetType()拿到的是Condition<string>这类泛型实例的类型,不是泛型参数T的类型,所以原来的条件永远不会命中。
下面是调整后的完整解决方案:
步骤1:修改基接口ConditionBase
给基接口添加一个GetValue()方法,把值的格式化逻辑封装到泛型类内部,避免在循环里做复杂的类型判断:
public interface ConditionBase { Field Field { get; set; } ConditionOperator ConditionOperator { get; set; } // 添加统一获取格式化值的方法 string GetValue(); }
步骤2:更新泛型Condition<T>类
实现基接口的GetValue()方法,根据泛型参数T的类型做对应的格式化处理:
public class Condition<T> : ConditionBase { private Field _Field; private T _Value; private ConditionOperator _ConditionOperator; public Condition(Field field, T value, ConditionOperator condition) { _Field = field; _Value = value; _ConditionOperator = condition; } public Field Field { get => _Field; set => _Field = value; } public T Value { get => _Value; set => _Value = value; } public ConditionOperator ConditionOperator { get => _ConditionOperator; set => _ConditionOperator = value; } // 按类型格式化Value并返回 public string GetValue() { if (typeof(T) == typeof(string)) { return $"'{_Value}'"; } else if (typeof(T) == typeof(DateTime)) { return Helpers.FormatDate((DateTime)(object)_Value); } else { return _Value.ToString(); } } }
步骤3:简化循环生成URL的逻辑
现在可以直接调用GetValue()方法,不用再做类型判断,代码更简洁:
string url = ""; List<ConditionBase> Conditions = new List<ConditionBase>(); Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal)); Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual)); foreach (ConditionBase c in Conditions) { url += $"{c.Field} {c.ConditionOperator} {c.GetValue()} and "; } // 移除末尾多余的" and " if (!string.IsNullOrEmpty(url)) { url = url.TrimEnd(" and ".ToCharArray()); }
补充说明
如果不想用GetValue()方法,也可以在基接口里添加object Value { get; }属性,在Condition<T>里实现为public object Value => _Value;,但这样循环里还是需要做类型判断,不如封装方法优雅。
内容的提问来源于stack exchange,提问作者Tim Hutchison
相关产品推荐
相关产品推荐

