原来Queryable是这样实现的..

一直没去细想为什么Enumerable和Queryable提供了两套签名一致的方法.今天在扩展IQToolkit,使之支持Insert/Update/Delete的过程中,遇到了问题,用Reflector看了一下Queryable类的源码,顿时醍醐灌顶.

在给代表数据库表格的类EntityTable(实现了IQueryable<TEntity>接口)添加一个扩展方法Delete(Expression<Predicate<TEntity>>)来做生成Delete语句的标识时,发现这个方法被直接调用了,觉得很郁闷.明明微软自己的Where, Select等方法都没被调用,而是作为Expression给传到了QueryProvider里, 凭什么我自己写的方法你就不给翻译一下传过去,而是当场执行呢?

不对啊,First, Single之类的方法也是当场执行的啊,难道编译器会根据方法的返回类型(是不是相同的IQueryable<T>)来决定如何对待它们?或者,可能有某个应用于方法上的Attribute,可以控制编译器这方面的行为?

还是看看Queryable里的代码是怎么写的吧.打开Reflector一看Queryable.First方法,马上明白了:

public static TSource First<TSource>(this IQueryable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return source.Provider.Execute<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression }));
}

晕了,原来根本不是编译器在捣鬼!这方法纯粹是一混蛋,屁事不干的主.不单屁事不干,还指使别人说,你再来调用我吧..

再看Queryable.Where:

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    return source.Provider.CreateQuery<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression, Expression.Quote(predicate) }));
}

First和Where的区别在于两者调用了不同的方法,一个要求直接执行对应的动作,一个要求返回一个新的IQueryable<T>对象以推迟实际行为的发生.

哎,这世界上怎么那么多比我聪明的人呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值