如何通过反射设置EntityField<T>对象的Value属性?
如何通过反射访问EntityField的Value属性?
我参考了相关技术问答,尝试通过反射获取对象的一个属性——这个属性是继承自EntityField类的对象,它有一个需要访问的Value属性。虽然找到了一些思路,但没能写出正确的代码。目前我的尝试和原始代码都存在问题,想请教怎么正确通过反射设置这个Value属性?
我的尝试代码
var parent = entity.GetType().GetProperty("Property"); parent.GetType().GetProperty("Value").SetValue(parent, newValue); // parent.GetType() 结果为null (parent as EntityField<T>).Value = newValue; // 不确定如何动态设置T,因为它可以是任意系统类型
主代码(原始代码)
private static void SetValues(JObject obj, EntityBase entity) { // entity.GetType().GetProperty("Property") 返回一个EntityField对象 // 我需要设置 EntityField.Value = obj["Value"] // 当前代码是设置 EntityField = obj["Value"],这会抛出错误 entity.GetType().GetProperty("Property").SetValue(entity, obj["Value"], null); }
EntityField类定义
public class EntityField<T> : EntityFieldBase { private Field _Field; private T _Value; public EntityField(Field field, T value){ this._Field = field; this._Value = value; } public Field Field { get { return this._Field; } set { if (this._Field != value) { this._Field = value; } } } public T Value { get { return this._Value; } set { if (!EqualityComparer<T>.Default.Equals(this._Value, value)) { this._Value = value; this._IsDirty = true; } } } }
解决方案
你的问题核心在于搞混了PropertyInfo和实际的属性对象。entity.GetType().GetProperty("Property")返回的是PropertyInfo类型的实例,不是EntityField<T>的对象,所以直接调用它的GetType()去拿Value属性肯定不对。
正确的步骤应该是这样:
- 获取目标属性的PropertyInfo:先拿到
entity上名为"Property"的属性元信息。 - 获取该属性的实际实例对象:通过
PropertyInfo.GetValue(entity)拿到真正的EntityField<T>实例。 - 获取EntityField
的Value属性的PropertyInfo :不管泛型参数T是什么,我们可以通过反射找到Value这个属性(因为所有EntityField<T>都定义了这个属性)。 - 将JToken值转换为T类型:因为
obj["Value"]是JToken,需要转换成EntityField<T>对应的T类型才能赋值。 - 设置Value属性的值:调用
SetValue把转换后的值赋给EntityField<T>实例的Value属性。
下面是修改后的完整代码:
private static void SetValues(JObject obj, EntityBase entity) { // 1. 获取目标属性的PropertyInfo var propertyInfo = entity.GetType().GetProperty("Property"); if (propertyInfo == null) return; // 2. 获取实际的EntityField<T>对象实例 var entityFieldInstance = propertyInfo.GetValue(entity); if (entityFieldInstance == null) return; // 3. 获取EntityField<T>的Value属性的PropertyInfo var valuePropertyInfo = entityFieldInstance.GetType().GetProperty("Value"); if (valuePropertyInfo == null) return; // 4. 把JToken转换成对应的T类型 var targetType = valuePropertyInfo.PropertyType; var convertedValue = obj["Value"].ToObject(targetType); // 5. 设置Value属性的值 valuePropertyInfo.SetValue(entityFieldInstance, convertedValue); }
如果需要让方法更通用,支持任意属性名,可以改成这样:
private static void SetEntityFieldValue(JObject obj, EntityBase entity, string propertyName) { var propertyInfo = entity.GetType().GetProperty(propertyName); if (propertyInfo == null) return; var entityFieldInstance = propertyInfo.GetValue(entity); if (entityFieldInstance == null) return; var valuePropertyInfo = entityFieldInstance.GetType().GetProperty("Value"); if (valuePropertyInfo == null) return; var targetType = valuePropertyInfo.PropertyType; var convertedValue = obj["Value"].ToObject(targetType); valuePropertyInfo.SetValue(entityFieldInstance, convertedValue); }
为什么你的尝试出错了?
parent.GetType().GetProperty("Value")这里的parent是PropertyInfo,不是EntityField<T>对象,所以找不到Value属性,自然会出问题。(parent as EntityField<T>)同样错误,因为parent是PropertyInfo,根本转不成EntityField<T>。你需要先调用GetValue(entity)拿到实际的字段对象,再去处理。
内容的提问来源于stack exchange,提问作者Tim Hutchison
相关产品推荐
相关产品推荐

