最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html

 

关于我和表达式树

  其实我也没有深入了解表达式树一些内在实现的原理,所以具体来说它到底是个什么东西我也不是很清楚,我的理解只是他是可以将'部分'委托构造成对象,方便我们对他进行解析; 虽然我没有完全搞懂表达式树,但这并不妨碍我使用它(如果以后有时间,我想我会更深入的去和它接触一下)

Lamda + 表达式树的性能瓶颈

  对于Lamda表达式树我的感觉是又爱又恨

  书写和阅读方面,无疑是非常成功的,他大大的减少了书写难度,增加了可读性

  但另一方面,在程序的性能上又是如此的糟糕

  来看下面一个栗子:

static void Main()
{
    Where1(u => u.Name == "1");
    Where2(u => u.Name == "1");
}

public static void Where1(Expression<Func<User, bool>> expr)
{

}

public static void Where2(Func<User, bool> expr)
{

}

  栗子中的 Where1 和 Where2 两个方法,唯一的不同,一个是委托,一个是表达式树

  同样运行Where1和Where2 一万次,Where2是0ms,Where1是57ms

  也就是说从Func<User, bool>转为Expression<Func<User, bool>>一万次需要57ms

  这对于我这样一个追求性能的人来说,实在是有点难受!

  到不至于不能接受,只有有点难受

  但从另一方面我也在考虑,为什么像这样的lamda不能直接预编译成Expression呢?期待微软的优化吧~

伪框架

  为什么我的标题中的框架为带有引号?

  因为我觉得这其实是一个伪框架

  但他确实能帮助我们更好的解析Expression对象,或许应该把他称之为解决方案或是别的

  不过~管他呢!能用就行了

你应该了解的Expression

  刚才说了虽然我也没有完全搞懂,但是有些东西还是应该知道的
比如:

  • 以Expression作为基类的子类一共有多少个
  • 他们分别是干什么的

  第一个问题比较简单

  1. 现在在vs中敲下 System.Linq.Expressions.Expression
  2. 然后按F1
  3. 如果顺利的话,你现在已经打开了"MSDN"
  4. 如果没有的话就手动点一下吧
  5. 然后滚动到屏幕最下面

干货!表达式树解析"框架"(1)

  

  好了这里看到的就是所有`public`的子类(其实没有公开的还有更多)

  至于他们分别是干什么用的,每一个都有自己不同的用法,这里不可能一一说明了,下面的内容也只会涉及到一部分,其他就要自己慢慢研究了

  举个栗子:

BinaryExpression ----表示包含二元运算符的表达式

最基础的用法就是它的三个属性Left ,Right ,NodeType 
Left 获取二元运算的左操作数。
Right 获取二元运算的右操作数。
NodeType 获取此 Expression 的节点类型。
it = it.Name == "blqw"就是一个BinaryExpression
Left = it.Name
Right = "blqw"
NodeType = Equals

  大概就是这么一个意思吧

效果预览

干货!表达式树解析"框架"(1)

框架结构

  嗯.允许我还是叫他框架吧,毕竟听上去比较高端大气上档次啊

干货!表达式树解析"框架"(1)

  暂时是这样

  • Parsers文件夹里面的是具体对应每一种表达式树的解析的具体实现
  • ExpressionParser     表达式树解析器抽象基类,实现IExpressionParser
  • ExpressionTypeCode   枚举,枚举了所有的类型的表达式树
  • IExpressionParser    表达式树解析器接口
  • Parser          调用解析器的静态对象,也可以看作入口或工厂,根据表达式树类型调用具体类
  • ParserArgs        解析器参数,在解析表达式树的方法中保持传递,可以保存解析中所使用的参数和保存解析结果

代码

    public class ParserArgs
    {
        public ParserArgs()
        {
            Builder = new StringBuilder();
        }

        public StringBuilder Builder { get; private set; }

        public IList<ParameterExpression> Forms { get; set; }

        public readonly string[] FormsAlias = { "it", "A", "B", "C", "D", "E" };
    }
ParserArgs

相关文章: