Expression.Convert似乎绕过MethodInfo(第三个参数)?

时间:2015-08-06 16:27:05

标签: c# linq entity-framework linq-to-entities expression-trees

我不明白为什么这样做。表达对我来说是一个相当新的东西,尤其是在LinqToEntity中使用时。这是我的代码:

var getInt = GetType().GetMethod("getAnInt", BindingFlags.Static | 
                                             BindingFlags.NonPublic);
var p = Expression.Parameter(typeof(Student));            
var id = Expression.Property(p, "ID");      
var eq = Expression.Equal(Expression.Convert(id, typeof(int), getInt), 
                          Expression.Constant(2));
var pred = Expression.Lambda<Func<Student, bool>>(eq, p);
//use the pred in query
foreach(var student in myContext.Students.Where(pred)){
    //this always print ID 2 (which equals to the constant above);
    //no matter what is returned by the getAnInt method
    System.Diagnostics.Debug.Print(student.ID);
}
//the getAnInt method 
static int getAnInt(string dummy){
   return 100;
}

事实上,我只是在尝试(不是工作中的实际问题)。数据库表中的ID字段是varchar,其格式为整数(可转换为int)。我正在尝试将id转换为int(但不使用int.Parse静态方法,因为我正在尝试另一种方法),然后再与int常量进行比较。起初我的getAnInt返回了int.Parse(dummy)并且工作正常但是 然后我尝试更改它以使其返回任意整数。结果是 令人惊讶的是,无论它返回什么整数,id似乎都转换为int确定(好像它被int.Parse转换)并与Expression.Constant(2)进行比较,始终过滤ID为2的学生。

我希望id的转换值应该是getAnInt的返回值,但它似乎是旁路的。 我还尝试制作另一段代码来测试Expression.Convert,这表明它可以正常运行:

var t = typeof(Form1).GetMethod("Test", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
var p = Expression.Parameter(typeof(string));
var c = Expression.Convert(p, typeof(int), t);
var e = Expression.Equal(c, Expression.Constant(10));
var f = Expression.Lambda<Func<string,bool>>(e, p);
var k = f.Compile()("1"); //test the value of k to see if it works.
                          //the parameter will be by-passed
                          //the return value of Test is obtained 
                          //and compared against constant 10 as expected.

static int Test(string dummy){
   return 10; //this makes the k above return true;
              //any other value makes it return false;
              //It seems to work OK here.
}

这里唯一的区别是第一个代码是在LinqToEntity的上下文中测试的,而第二个代码是直接尝试执行编译的表达式。 我确定我的Students个实体对我的测试有id所有感兴趣的值。 如你所见,它只是一个实体集,很简单。我不知道如何调试Expression。第二个测试是我试图确认我是否正确理解Expression.Convert

我希望你能在我的第一段代码中发现错误,或者至少给我任何关于可能出错的方向/建议。非常感谢你的帮助。

0 个答案:

没有答案