Expression Tree-学习构建表达式树
从本人的历程来看,我们首先了解System.Linq.Expression这个类开始比较好,通过研究它的方法和属性,
我们可以运行一些实例来加深对表达式树的理解和大致了解这个类提供的功能集合。2010 版本的类链接为:http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx。
Expression的方法非常丰富大致这么几类:
1,操作:加减乘除,一元操作,位操作,布尔操作,赋值,等等,一种编程语言的各种操作。
2,语句:条件语句,循环,Try catch,Finalize等各种编程语言的语句。
3,invoke,call,Block等一些神秘语方法。
总之完全可以把一段代码用这些方法来翻译构建。
来试试一些熟悉的方法
1,操作
1.1 Add(Expression, Expression),左右相加,实例表示调用add执行1+2.
// Add the following directive to your file:
// using System.Linq.Expressions;
// This expression adds the values of its two arguments.
// Both arguments must be of the same type.
Expression sumExpr = Expression.Add(
Expression.Constant(1),
Expression.Constant(2)
);
// Print out the expression.
Console.WriteLine(sumExpr.ToString());
// The following statement first creates an expression tree,
// then compiles it, and then executes it.
Console.WriteLine(Expression.Lambda<Func<int>>(sumExpr).Compile()());
// This code example produces the following output:
//
// (1 + 2)
// 3
1.2 AddAssign(Expression, Expression) 类似+=操作符
// Add the following directive to your file:
// using System.Linq.Expressions;
// The Parameter expression is used to create a variable.
ParameterExpression variableExpr = Expression.Variable(typeof(int), "sampleVar");
// The block expression enables you to execute several expressions sequentually.
// In this bloc, the variable is first initialized with 1.
// Then the AddAssign method adds 2 to the variable and assigns the result to the variable.
BlockExpression addAssignExpr = Expression.Block(
new ParameterExpression[] { variableExpr },
Expression.Assign(variableExpr, Expression.Constant(1)),
Expression.AddAssign(
variableExpr,
Expression.Constant(2)
)
);
// Print out the expression from the block expression.
Console.WriteLine("The expressions from the block expression:");
foreach (var expr in addAssignExpr.Expressions)
Console.WriteLine(expr.ToString());
Console.WriteLine("The result of executing the expression tree:");
// The following statement first creates an expression tree,
// then compiles it, and then executes it.
Console.WriteLine(Expression.Lambda<Func<int>>(addAssignExpr).Compile()());
// This code example produces the following output:
//
// The expressions from the block expression:
// (sampleVar = 1)
// (sampleVar += 2)
// The result of executing the expression tree:
// 3
2,语句
1,IfThen,
// Add the following directive to the file:
// using System.Linq.Expressions;
bool test = true;
// This expression represents the conditional block.
Expression ifThenExpr = Expression.IfThen(
Expression.Constant(test),
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }),
Expression.Constant("The condition is true.")
)
);
// The following statement first creates an expression tree,
// then compiles it, and then runs it.
Expression.Lambda<Action>(ifThenExpr).Compile()();
// This code example produces the following output:
//
// The condition is true.
3,辅助方法
Call(Expression, MethodInfo) 类似反射方式调用方法
// Add the following directive to your file:
// using System.Linq.Expressions;
// This expression represents a call to an instance method without arguments.
Expression callExpr = Expression.Call(
Expression.Constant("sample string"), typeof(String).GetMethod("ToUpper", new
Type[] { }));
// Print out the expression.
Console.WriteLine(callExpr.ToString());
// The following statement first creates an expression tree,
// then compiles it, and then executes it.
Console.WriteLine(Expression.Lambda<Func<String>>(callExpr).Compile()());
// This code example produces the following output:
//
// "sample string".ToUpper
// SAMPLE STRING
现在应该应该明白表达式树具有翻译代码的功能了吧,从目前的实例来看就是找抽,好好的人话不说,偏要用
甄嬛体,不如直接用if else =, when来的痛快。但是别忘了,用表达式树写的代码类似从硬编码变成了动态
可配置了一样,很像javascript这种动态语言了呢?拿出来可以直接用eval()执行。
最后一段简单的加减翻译:
<Expression>
<Add>
<Arg>20</Arg>
<Arg>100</Arg>
</Add>
<Subtract>
<Arg>200</Arg>
</Subtract>
</Expression>
static void Main(string[] args)
{
string exampleStr = "<Expression><Add><Arg>20</Arg><Arg>100</Arg></Add><Subtract><Arg>200</Arg></Subtract></Expression>";
Expression customeExression = GetExpression(exampleStr);
Console.WriteLine("the caculate expression is :");
Console.WriteLine(customeExression.ToString());
Console.WriteLine("the result is :");
Console.WriteLine(Expression.Lambda<Func<int>>(customeExression).Compile().Invoke());
Console.Read();
}
static Expression GetExpression(string exression)
{
Expression calTree = Expression.Constant(0);
XmlDocument doc = new XmlDocument();
doc.LoadXml(exression);
XmlNode rootNode = doc.DocumentElement;
foreach (XmlNode childNode in rootNode.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Element)
{
Expression expressionItem = GetExpression(childNode);
if (expressionItem != null)
{
calTree = Expression.Add(calTree, expressionItem);
}
}
}
return calTree;
}
static Expression GetExpression(XmlNode node)
{
Expression expression = null;
if (node.Name == "Add")
{
expression = Expression.Add(Expression.Constant(int.Parse(node.ChildNodes[0].InnerText)), Expression.Constant(int.Parse(node.ChildNodes[1].InnerText)));
}
else if (node.Name == "Subtract")
{
expression = Expression.Subtract(Expression.Constant(0), Expression.Constant(int.Parse(node.ChildNodes[0].InnerText)));
}
return expression;
}