去掉L,这个类似:
object o = 2L;
int ii = (int)o;
没办法处理的。
我的需求是:
对象被json序列化,然后再反序列化,得到一个字典,字典中,Age的值会从 int 变成 long。
我这个代码的目的就是把字典的值转换为对象的属性值。
@519740105: 那就把object写成long
@519740105: 或者Expression Call Convert.ToInt32()
@jello chen: 具体的类型不确定,所以需要用object。
我的实际需求场景是:
定义一个可扩展实体,该实体具备一个可扩展的数据属性(类似于复杂数据类型)
当把这个实体存储于数据库时,可扩展数据属性的内容通过json格式存储,当从数据库读取时,将json转换为字典,逐个识别扩展数据属性对象属性定义,然后把内容填写上。
@jello chen: 在进行数据写时,本来也可以通过GetValue或SetValue来实现,考虑到性能,便想到了用ExpressionTree。
事实上,当使用Action<object, object>设置值时,因value是long,也需要经过转换,此时使用Expression.Convert是能转换成功。但是,通过Expression的多次转换就出现了这个问题。
@jello chen:
public static Action<object, object> MakeSetLambda(this PropertyInfo propertyInfo, Type declaringType = null) { var paramInst = Expression.Parameter(typeof(object)); var paramValue = Expression.Parameter(typeof(object)); var bodyInst = Expression.Convert(paramInst, declaringType ?? propertyInfo.DeclaringType); var bodyValue = Expression.Convert(paramValue, propertyInfo.PropertyType); var bodyExp = Expression.Call(bodyInst, propertyInfo.GetSetMethod(), bodyValue); var result = Expression.Lambda<Action<object, object>>(bodyExp, paramInst, paramValue).Compile(); return result; }
模拟调用:
PropertyInfo propertyInfo = typeof(Test).GetProperty("Age"); var setter = MakeSetLambda(propertyInfo); object age = 2L; object instance = new Test(); setter(instance, age);//此处抛出异常
@519740105: 嗯,改成这样试试:
var bodyValue = Expression.Convert(paramValue, typeof(int), typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(object) }));
@jello chen: 关键是这个 int 是不确定的。现在只是发现了long到int出现了问题。代码还得按照我的思路来。
@519740105: 胡乱写了下:
public static Action<object, object> MakeSetLambda(this PropertyInfo propertyInfo, Type declaringType = null) { var paramInst = Expression.Parameter(typeof(object)); var paramValue = Expression.Parameter(typeof(object)); var type = declaringType ?? propertyInfo.DeclaringType; var bodyInst = Expression.Convert(paramInst, type); var bodyValue = Expression.Convert(paramValue, propertyInfo.PropertyType, GetConvertMethodInfo(propertyInfo.PropertyType)); var bodyExp = Expression.Call(bodyInst, propertyInfo.GetSetMethod(), bodyValue); var result = Expression.Lambda<Action<object, object>>(bodyExp, paramInst, paramValue).Compile(); return result; } static MethodInfo GetConvertMethodInfo(Type type) { //可缓存 var typeCode = TypeInfo.GetTypeCode(type); var mi = typeof(Convert).GetMethod("To" + typeCode, new Type[] { typeof(object) }); return mi; }
@jello chen: 恩,这也是一个办法。但是,就不能把我的这个 MakeStLambda 作为通用的 方法了。
我再想想。