c# – Explicit Boxing之间使用Expression.Convert不能正常工作
|
最近,当我开发自制的SQLite ORM时,我遇到了一些关于使用Expression Trees进行拳击的麻烦.我还在编码C#3.5.
总而言之,我将使用这个简单的类定义: [Table]
public class Michelle
{
[Column(true),PrimaryKey]
public UInt32 A { get; set; }
[Column]
public String B { get; set; }
}
因此,根据POCO类定义,我实例化了一个新对象,我的ORM引擎将该对象转换为记录并正确插入.现在的诀窍是,当我从SQLite中获取值时,我得到了一个Int64. 我认为我的委托制定者是好的,因为它是一个Action< Object,Object>但我仍然有InvalidCastException.似乎尝试将Object(参数,Int64)强制转换为UInt32.不幸的是它不起作用.我试图添加一些Expression.Constant和Expression.TypeAs(对于值类型对象,它实际上没有帮助). 所以我想知道我的二传手生成中出了什么问题. 下面是我的setter生成方法: public static Action<Object,Object> GenerateSetter(PropertyInfo propertyInfo)
{
if (!FactoryFastProperties.CacheSetters.ContainsKey(propertyInfo))
{
MethodInfo methodInfoSetter = propertyInfo.GetSetMethod();
ParameterExpression parameterExpressionInstance = Expression.Parameter(FactoryFastProperties.TypeObject,"Instance");
ParameterExpression parameterExpressionValue = Expression.Parameter(FactoryFastProperties.TypeObject,"Value");
UnaryExpression unaryExpressionInstance = Expression.Convert(parameterExpressionInstance,propertyInfo.DeclaringType);
UnaryExpression unaryExpressionValue = Expression.Convert(parameterExpressionValue,propertyInfo.PropertyType);
MethodCallExpression methodCallExpression = Expression.Call(unaryExpressionInstance,methodInfoSetter,unaryExpressionValue);
Expression<Action<Object,Object>> expressionActionObjectObject = Expression.Lambda<Action<Object,Object>>(methodCallExpression,new ParameterExpression[] { parameterExpressionInstance,parameterExpressionValue });
FactoryFastProperties.CacheSetters.Add(propertyInfo,expressionActionObjectObject.Compile());
}
return FactoryFastProperties.CacheSetters[propertyInfo];
}
所以基本上: // Considering setter as something returned by the generator described above // So: // That one works! setter(instance,32u); // This one... hm not really =/ setter(instance,64); 我应该添加另一个Expression.Convert,但我真的不知道如何使它工作.因为已经有人应该(尝试)从任何Object转换为属性类型(在我的例子中是UInt32类型). 有什么想法解决它吗? 解决方法
对于这个答案,假设定义如下:
object myColValueFromTheDatabase = (object)64L; Expression.Convert静态地确定如何执行转换.就像C#一样.如果您编写(uint)myColValueFromTheDatabase,这将无法在运行时成功,因为取消装箱只是不起作用. Expression.Convert也做了一个简单的拆箱尝试.这就是它失败的原因. 您需要执行以下任一操作: >(uint)(long)myColValueFromTheDatabase 在情况(1)中,您需要首先取消装箱到完全匹配类型,然后更改位.案例(2)使用一些辅助方法解决了这个问题.案例(1)更快. 要使用表达式API执行此操作,请插入另一个Expression.Convert. 这应该让你开始: public static T LogValue<T>(T val)
{
Console.WriteLine(val.GetType().Name + ": " + val);
return val;
}
static void Main(string[] args)
{
Expression myColValueFromTheDatabase = Expression.Convert(Expression.Constant(1234L),typeof(object));
myColValueFromTheDatabase = Expression.Call(typeof(Program),"LogValue",new[] { myColValueFromTheDatabase.Type },myColValueFromTheDatabase); //log
Expression unboxed = Expression.Convert(myColValueFromTheDatabase,typeof(long));
Expression converted = Expression.Convert(unboxed,typeof(uint));
var result = Expression.Lambda<Func<uint>>(converted).Compile()();
Console.WriteLine(result);
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
