来自通用基类中的字段的 C# 反射 GetValue
Posted
技术标签:
【中文标题】来自通用基类中的字段的 C# 反射 GetValue【英文标题】:C# reflection GetValue from a field in generic base class 【发布时间】:2012-07-11 23:02:45 【问题描述】:问题是我们不能获取仅位于具有泛型类型的基类中的字段(非泛型)的值。 请参阅下面的代码 sn-p。打电话
f.GetValue(a)
将抛出异常并显示消息:不能对 Type.ContainsGenericParameters 为 true 的类型的字段执行后期绑定操作。
class Program
static void Main(string[] args)
Type abstractGenericType = typeof (ClassB<>);
FieldInfo[] fieldInfos =
abstractGenericType.GetFields(BindingFlags.Public | BindingFlags.Instance);
ClassA a = new ClassA("hello");
foreach(FieldInfo f in fieldInfos)
f.GetValue(a);// throws InvalidOperationhException
internal class ClassB<T>
public string str;
public ClassB(string s)
str = s;
internal class ClassA : ClassB<String>
public ClassA(string value) : base(value)
我们的设计要求我们在获得任何实际对象的实例之前首先获得 FieldInfo。所以我们不能使用
Type typeA = abstractGenericType.MakeGenericType(typeof(string));
FieldInfo[] fieldInfos = typeA.GetFields();
谢谢
【问题讨论】:
发布的问题没有多大意义。您将必须使用对象实例来调用GetValue()。所以只需使用a.GetType()
来获取具体的泛型类型,没有必要通过不完整的类型。
【参考方案1】:
我猜问题出在这一点上,泛型类是使用特定类型动态编译的。泛型类型也可以定义为
internal class ClassB<T>
public T value;
public string str;
public ClassB(string s)
str = s;
那么你在获取字段“value”的值时会遇到问题。解决方法是使用 .GetType() 直接检索类型,或者创建一个新的基类,而不使用包含您要访问的字段的通用参数。
【讨论】:
【参考方案2】:如果您灵活并且愿意使用属性而不是字段,则可以通过在泛型基类上放置非泛型接口来完成您想要的事情。这是原始代码的重构版本,显示了更改和概念。
class Program
public static void Main(string[] args)
Type interfaceType = typeof(IGetStr);
PropertyInfo[] propertyInfos = interfaceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
ClassA a = new ClassA("hello");
foreach (PropertyInfo p in propertyInfos)
var myValue = p.GetValue(a, null); // does not throw InvalidOperationException
internal interface IGetStr
string StringValue get; set;
internal class ClassB<T> : IGetStr
public string str;
public ClassB(string s)
str = s;
public string StringValue
get
return str;
set
str = value;
internal class ClassA : ClassB<String>
public ClassA(string value)
: base(value)
接口是访问泛型类的非泛型属性的好方法。使用如图所示的接口,只要您使用 IGetStr 的接口,您就可以获得从 ClassB 继承的任何类的名为“StringValue”的属性,而不管泛型类型如何。
您也可以将您的“ClassA”对象转换为 IGetStr,以下将起作用。 (非常适合所有从您的通用基础继承的项目列表)
var result = ((IGetStr)a).StringValue;
【讨论】:
以上是关于来自通用基类中的字段的 C# 反射 GetValue的主要内容,如果未能解决你的问题,请参考以下文章