using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace 表达式树
{
class Program
{
static void Main(string[] args)
{
//1.构建简单的表达式树
//1+2+3
var EXP1 = Expression.Constant(1);
var exp2 = Expression.Constant(2);
var exp12 = Expression.Add(EXP1, exp2);
var exp3 = Expression.Constant(3);
var exp123 = Expression.Add(exp12, exp3);
////转换成lambda表达式才能调用compile()生成委托
Expression<Func<int>> lambdaExp = Expression.Lambda<Func<int>>(exp123);
Console.WriteLine(lambdaExp.Compile()());
////2.对于比较简单的(不能有赋值、代码块)表达式,可以直接使用lambd表达式
Expression<Func<int>> lambdExp = () => 1 + 2 + 3;
Console.WriteLine(lambdaExp.Compile()());
//3.代码块表达式
//static int HelloWorld()
//{
// Console.Write("Hello World!");
// return 42;
//}
BlockExpression blockExp = Expression.Block
(
Expression.Call
(
null,
typeof(Console).GetMethod("Write", new[] { typeof(string) }),
Expression.Constant("Hello World")
),
Expression.Constant(42)
);
Expression<Func<int>> lambdBlock = Expression.Lambda<Func<int>>(blockExp);
Console.WriteLine(lambdBlock.Compile()());
//4.通过 Expression 类创建表达式树
// lambda:num => num == 0
ParameterExpression pExpression = Expression.Parameter(typeof(int),"num"); //参数:num
ConstantExpression cExpression = Expression.Constant(0); //常量:0
//BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); //表达式:num == 0
BinaryExpression bExpression= Expression.Equal(pExpression, cExpression);
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda 表达式:num => num == 0
Console.WriteLine(lambda.Compile()(12));
//5.表达式与反射应用
//请用表示式实现一个动态逻辑,可以更新任意一种数据实体类的集合,比如list<book>中每一个元素的指定属性;
Book b1 = new Book() { Author = "1", Name = "zahngsna" };
List<Book> list_book = new List<Book>();
for (int i = 0; i < 1000000; i++)
{
list_book.Add(b1);
}
var sw = new Stopwatch();
sw.Start();
////表达式优化
SetAllProperty_Exp<Book, string>(list_book, "Author", "123");
sw.Stop();
Console.WriteLine("表达式优化耗时:" + sw.ElapsedMilliseconds);
sw.Restart();
////反射
SetAllProperty<Book>(list_book, "Author", "458");
sw.Stop();
Console.WriteLine("反射耗时:" + sw.ElapsedMilliseconds);
//6. 思考题a. xy+x+y
//法一
Expression<Func<int, int, int>> lambdEx = (x, y) => x * y + x + y;
Console.WriteLine("表达式:" + lambdEx + ",值:" + lambdEx.Compile()(1, 2));
////法二
var xExp = Expression.Parameter(typeof(int), "x");
var yExp = Expression.Parameter(typeof(int), "y");
var xyExp = Expression.Multiply(xExp, yExp);
var xplusyExp = Expression.Add(xExp, yExp);
var exp = Expression.Add(xyExp, xplusyExp);
Expression<Func<int, int, int>> lambdExp1 = Expression.Lambda<Func<int, int, int>>(exp, new[] { xExp, yExp });
Func<int, int, int> del = lambdExp1.Compile();
Console.WriteLine("表达式:" + lambdExp1 + ",值:" + del(1, 2));
// 思考题b. Console.WriteLine("hi")
//法一
Expression<Action<string>> lambdExp2 = (h) => Console.WriteLine(h);
lambdExp2.Compile()("hi");
Console.WriteLine(lambdExp2);
//法二
var parameterExp = Expression.Parameter(typeof(string), "h");
var methodInfo = typeof(Console).GetMethod("WriteLine", new[] { typeof(string) });
var bodyExp = Expression.Call(null, methodInfo, parameterExp);
var lambdexp = Expression.Lambda<Action<string>>(bodyExp, parameterExp);
lambdexp.Compile()("h12");
Console.ReadKey();
}
class Book
{
public string Author { get; set; }
public string Name { get; set; }
}
static void SetAllProperty<T>(List<T> list, string propertyName, object propertyValue)
{
var _type = typeof(T);
PropertyInfo propertyInfo = _type.GetProperty(propertyName);
foreach (T t in list)
{
propertyInfo.SetValue(t,propertyValue,null);
}
}
static void SetAllProperty_Exp<T,K>(List<T> list,string propertyName,K propertyValue)
{
var _type = typeof(T);
PropertyInfo propertyInfo = _type.GetProperty(propertyName);
var methodInfo = propertyInfo.GetSetMethod();
//参数t
var invokeObjExpr = Expression.Parameter(typeof(T), "t");
//参数propertyValue
var properytValuExp = Expression.Parameter(propertyInfo.PropertyType, "propertyValue");
//主体方法
var setMethodExp = Expression.Call(invokeObjExpr, methodInfo, properytValuExp);
//强类型的委托
var lambdaExp = Expression.Lambda<Action<T, K>>(setMethodExp, invokeObjExpr, properytValuExp);
var del = lambdaExp.Compile();
foreach (T t in list)
{
// propertyInfo.SetValue(t,propertyValue,null);
del(t, propertyValue);
}
}
}
}