手工把LINQ转成表达式(五) let

来源:互联网 发布:虚拟摇杆软件 编辑:程序博客网 时间:2024/05/22 00:21

let语句的处理比较特殊,先看一个简单例子:

int[] array = { 1, 3, 3 };
IQueryable<int> A = array.AsQueryable();
var q = from a in A
        let i = a + 1
        select new { i };

编译后表达式为:

System.Int32[].Select(a => new <>f__AnonymousType0`2(a = a, i = (a + 1))).Select(<>h__TransparentIdentifier0 => new <>f__AnonymousType1`1(i = <>h__TransparentIdentifier0.i))

观察可以看到let等于是创建了一个新的匿名类型,这个类型包含了它之前的所有用到的linq内变量再加上let自己定义的变量,然后再用select选出。这样我们就可以把let视为一个select,上面的linq可以假设为

from a in A

select B in new  { a = a , i = a + 1 }

select new {  B.i }

当然正式的linq是不支持这么写的,这只是为了方便写处理代码:

                case "query_let_expression":                    var id = expNode.ChildNodes[1].FindTokenAndGetText();                    var last = _linqVariables.Peek();                    EnterScope(new[] { last.NextParameter });                    var letBody = ProcessExpression(expNode.LastChild);                    LeaveScope();                    var let = GetAnonymousExpression(                                    new[] { last.NextParameter.Name, id },                                    new[] { last.NextParameter.Type, letBody.Type },                                    new[] { last.NextParameter, letBody });                    var letexp = Expression.Call(MakeMethod(op, last.NextParameter.Type, let.Type),                                                last.Self,                                                Expression.Lambda(let, last.NextParameter));                    _linqVariables.Push(new LINQContext                    {                        Parameter = last.NextParameter,                        Name = GetTransparentIdentifier(),                        Self = letexp,                    });                    break;


之前let的扩展方法就被定义成:

extensionMethods["let"] = extensionMethods["select"];

 

原创粉丝点击