我已经实现了简单的IQueryable
和IQueryProvider
类,它们收集有关LINQ表达式树的统计数据。这部分工作正常。接下来,我想将表达式树传递给默认的LINQ-to-Objects提供程序进行评估,因为我不需要以任何不同的方式执行它。换句话说,我希望我的提供者收集统计信息作为副作用,将查询传递给默认的LINQ实现。
但是,我无法获得默认提供程序的句柄。我认为我可以简单地保存对原始IEnumerable
集合的引用,然后返回默认提供程序(来自我的自定义IQueryable
),如:
IQueryProvider IQueryable.Provider
{
get { return _my_provider.OriginalIEnum().AsQueryable().Provider; }
}
但这不能正常工作。代码最终抛出StackOverflowException
。我认为正在发生的事情(从调试模式中的单步执行中收集)是LINQ运行时从上面的方法中提取提供程序,然后从我的自定义IQueryable
中获取表达式树,然后它注意到顶级表达式是我的自定义IQueryable
。所以它重新开始这个过程,试图找到合适的提供者。它会无休止地执行,直到发生堆栈溢出。
现在,我唯一能想到的是创建另一个访问者,该访问者生成另一个表达式树,其中删除了自定义IQueryable
节点,以便LINQ运行时将调用默认提供程序。这是相当多的工作,因为我需要访问每个叶子以确保没有嵌套的Call
表达式再次调用我的自定义IQueryable
。有更简单的方法吗?
感谢您的帮助。