在.NET Framework 3.5中提供了表达式目录树(Expression Tree),它是一种抽象语法树或者说它是一种数据结构。在了解他之前我们需要从委托说起,
在.NET中委托是使用delegate 关键字声明的一个引用类型,类似于 C++ 中的函数指针,你可以把委托理解为方法的别名,只不过他代表了一类的方法。委托是类型安全和可靠的。1.我们举一个例子来简单说明委托的使用,假设我们有一个人员组织库,我们要列出库中所有人员的名字,下面是代码:
public class Employe { public string Name { get; set; } public int Age { get; set; } public Employe(string name,int age) { this.Name = name; this.Age = age; } }
public delegate void ProcessEmployeDelegate(Employe emp); public class EmpDataBase{ Listlist = new List { new Employe("Cary",25), new Employe("James",34) }; public void ProcessEmploye(ProcessEmployeDelegate processEmploye) { foreach (Employe emp in list) { processEmploye(emp); } }}
class Program{ static void ShowEmpName(Employe emp) { "名字:{0}".FormatWriteLine(emp.Name); } static void Main() { EmpDataBase empdb = new EmpDataBase(); empdb.ProcessEmploye(ShowEmpName); }
}
下面是结果:
名字:Cary 名字:James |
上面我为String加了一个简单的扩展方法,代码如下:
public static void FormatWriteLine(this string format, params object[] args){ Console.WriteLine(string.Format(format, args));}
2.到.NET2.0时代,引入了匿名方法,使用匿名方法我们就不必创建单独的方法,而是将匿名方法直接作为参数传递。于是上面的主程序就可以改变为如下代码:
class Program{ static void Main() { EmpDataBase empdb = new EmpDataBase(); empdb.ProcessEmploye(delegate(Employe emp) { "名字:{0}".FormatWriteLine(emp.Name); }); } }
3.进入.NET3.X时代,我们又有了Lambda表达,可以将delegate关键字也去掉,让人彻底的看不见委托的影子,代码如下:
class Program{ static void Main() { EmpDataBase empdb = new EmpDataBase(); empdb.ProcessEmploye(emp=>"名字:{0}".FormatWriteLine(emp.Name)); } }
4.到此为止我们的主程序是不是简化了许多。不过我们还声明了一个ProcessEmployeDelegate委托,我们可以使用Action或Func来代替,Action 和Func 的功能没有什么区别,只是Action 没有返类型。代码如下:
public void ProcessEmploye(ActionprocessEmploye){ foreach (Employe emp in list) { processEmploye(emp); }}
5.了解了lambda表达式,其对应的具体语法树就是Expression Tree,其对应的相关API都在System.Linq.Expressions命名空间下,如下图:
我们来看下Expression类的结构,该类有四个属性:
Body:获取表达式的主体;
Parameters:获取Lambda表达示的参数; NodeType:得到树中某些节点的表达式类型(ExpressionType),这是一个有45种不同值的枚举类型,代表表达式节点的所有可能类型,如返回常数、 也可能返回参数、或者返回一个值是否小于另外一个(<),或者返回一个值是否大于另外一个(>),或者返回两个值的和( )等等。 Type:得到表达式的静态类型,在本例中,表达式的类型是Func。6.我们构建,遍历,修改表达式目录树,还可以执行表达式目录树,下面继续举几个例子来说明。找出下面字符串数字中以“C”开头的员工(x => x.StartsWith("C")):
String[] names = new string[2] { "Cary","James"};Expression> expression1 = (x) => x.StartsWith("C");"Expression is {0}\r\n".FormatWriteLine(expression1.ToString()); foreach (String name in names.Where(expression1.Compile())){ "{0 }".FormatWriteLine(name);}
7.找出人员库中年龄为25的员工,表达式为:Expression is age => (age.Age = 25)
ConstantExpression constEmpAge = Expression.Constant(25);ParameterExpression paramAge =Expression.Parameter(typeof(Employe), "age");MemberExpression mex =LambdaExpression.PropertyOrField(paramAge, "Age");BinaryExpression filter = Expression.Equal(mex, constEmpAge);Expression> expression2 = Expression.Lambda > (filter,new ParameterExpression[] { paramAge }); "Expression is {0}\r\n".FormatWriteLine(expression2.ToString());foreach (Employe emp in list.Where(expression2.Compile())){ "{0}:{1}".FormatWriteLine(emp.Name,emp.Age);}
8.我们还可以使用Expression Tree Visualizer来查看表达式目录树的相关信息,如下图:
Expression Tree Visualizer的使用将ExpressionTreeVisualizer中的.dll文件拷贝到..\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers.中。
本文没有过多深入的内容,只是希望给大家带来一些对Expression的基本认识,希望本文能对您有用。
转载自:
谢谢浏览!