C# 如何使用反射读取泛型类型相同但泛型参数不同的属性
问题原因
你的代码存在两个核心错误:
- 泛型类型匹配逻辑错误
typeof(AnalyzedParameter<>)是未绑定类型参数的泛型类型定义,而你业务类中的属性是绑定了类型参数的构造泛型类型(比如AnalyzedParameter<int>、AnalyzedParameter<string>),二者直接用==判断永远不会匹配,导致筛选出来的属性集合是空的。 - 强转类型不兼容
就算你能筛选到属性,直接把AnalyzedParameter<int>这类值类型参数的泛型实例强转为AnalyzedParameter<object>会抛出强制转换异常:C#的泛型协变只支持引用类型,值类型的泛型参数不支持协变转换。
解决方案
推荐两种实现方式,可根据场景选择:
方案1:新增非泛型接口(性能最优,推荐)
不需要改现有业务逻辑,只需要给泛型类加个非泛型的约束接口即可:
// 新增非泛型接口,暴露Valid属性 public interface IAnalyzedParameter { bool Valid { get; } } // 原有泛型类实现接口 public class AnalyzedParameter<T> : IAnalyzedParameter { public T Value { get; set; } public bool Valid { get; set; } }
然后校验方法改成:
public bool IsValid() { return GetType().GetProperties() // 筛选实现了IAnalyzedParameter接口的属性 .Where(prop => typeof(IAnalyzedParameter).IsAssignableFrom(prop.PropertyType)) .All(p => ((IAnalyzedParameter)p.GetValue(this))?.Valid ?? false); }
方案2:纯反射实现(不需要改原有类定义)
如果不能修改AnalyzedParameter<T>的定义,可以直接用反射读取Valid属性值:
public bool IsValid() { var analyzedParameterTypeDef = typeof(AnalyzedParameter<>); return GetType().GetProperties() // 正确匹配构造后的泛型类型 .Where(prop => prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == analyzedParameterTypeDef) .All(p => { var instance = p.GetValue(this); if (instance == null) return false; // 反射读取Valid属性值 return (bool)instance.GetType().GetProperty("Valid").GetValue(instance); }); }
内容的提问来源于stack exchange,提问作者Viacheslav Brovko
相关产品推荐
相关产品推荐

