表达式目录树学习笔记
第一堂课:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;//表达式目录树的命名空间
using System.Text;
using System.Threading.Tasks;
namespace 表达式目录树
{
class Program
{
static void Main(string[] args)
{
ExpressionShow();
Console.ReadKey();
}
#region 表达式目录树1
static void ExpressionShow()
{
//委托和表达式目录树的区别
{
Func<int, int, int> func = (m, n) => m * n + 2;//实际为:new Func<int,int,int>((m,n)=>m*n+2);
Expression<Func<int, int, int>> expression = (m, n) => m * n + 2;//Lambda表达式声明表达式目录树
//Expression<Func<int,int,int>> expression1=(m,n)=>
//{
// return m * n + 2;
//}
//表达式目录树:语法树,或者说是一种数据结构
int iResult1 = func.Invoke(12, 12);
int iResult2 = expression.Compile().Invoke(12, 12);//可以编译为委托后使用Invoke
}
//上面的Lambda是快捷生成表达式目录树的方式
//Queryable传递的是表达式目录树
{
Expression<Func<int, int, int>> expression = (m, n) => m * n + 2;
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "m");
ParameterExpression parameterExpression2 = Expression.Parameter(typeof(int), "n");
var multiply = Expression.Multiply(parameterExpression, parameterExpression2);
var constant = Expression.Constant(2, typeof(int));
var add = Expression.Add(multiply, constant);
Expression<Func<int, int, int>> myExpression = Expression.Lambda<Func<int, int, int>>(add,
new ParameterExpression[]
{
parameterExpression,
parameterExpression2
});
int iResult = myExpression.Compile().Invoke(11, 12);
int iResult1 = myExpression.Compile()(11, 12);//myExpression.Compile()是一个委托,所以也可以这样执行表达式目录树
}
//自己拼装表达式目录树
{
//常量
ConstantExpression conLeft = Expression.Constant(345);
ConstantExpression conRight = Expression.Constant(456);
BinaryExpression binary = Expression.Add(conLeft, conRight);//345+456
Expression<Action> actExpression = Expression.Lambda<Action>(binary, null);//null表示参数为空
//只能执行表示Lambda表达式的表达式目录树,即LambdaExpression或者Expression<TDelegate>类型
actExpression.Compile()();//()=>345+456
}
{
Console.WriteLine("变量表达式目录树");
ParameterExpression paraLeft = Expression.Parameter(typeof(int), "a");
ParameterExpression paraRight = Expression.Parameter(typeof(int), "b");
BinaryExpression binaryLeft = Expression.Multiply(paraLeft, paraRight);
ConstantExpression conRight = Expression.Constant(2, typeof(int));
BinaryExpression binaryBody = Expression.Add(binaryLeft, conRight);
Expression<Func<int, int, int>> lambda = Expression.Lambda<Func<int, int, int>>(binaryBody, paraLeft, paraRight);
Console.WriteLine(lambda.Compile()(3, 4));
Func<int, int, int> func = lambda.Compile();
Console.WriteLine(func(3, 4));
}
{
//Lambda方式创建表达式目录树
Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5");
//自定义拼凑表达式目录树
ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x");
var field = Expression.Field(parameterExpression, typeof(People).GetField("Id"));
var toString = typeof(People).GetMethod("ToString");
var toStringCall = Expression.Call(field, toString, new Expression[0]);
var equals = typeof(People).GetMethod("Equals");
var constant = Expression.Constant("5", typeof(string));
var equalsCall = Expression.Call(toStringCall, equals, new Expression[] { constant });
Expression<Func<People, bool>> expression =
Expression.Lambda<Func<People, bool>>(equalsCall, new ParameterExpression[]
{
parameterExpression
});
expression.Compile().Invoke(new People()
{
Id = 11,
Name = "Cgc",
Age = 28
});
}
//数据库以前用户拼接条件
{
string sql = "SELECT * From USER WHERE 1=1";
string name = "Cgc";
if (string.IsNullOrWhiteSpace(name))
{
sql += $"and name like '%{name}%'";//应该参数化,否则会被SQL注入
}
}
//现在entity framework查询的时候,需要一个表达式目录树
IQueryable<int> list = null;
//都不过滤
if (true)//只过滤A
{
Expression<Func<People, bool>> exp1 = x => x.Id > 1;
}
if (true)//只过滤B
{
Expression<Func<People, bool>> exp2 = x => x.Age > 10;
}
//都过滤
Expression<Func<People, bool>> exp3 = x => x.Id > 1 && x.Age > 10;
//list.Where();
{
//硬编码:性能最佳
People people = new People()
{
Id = 11,
Name = "cgc",
Age = 29
};
PeopleCopy peopleCopy = new PeopleCopy()
{
Id = people.Id,
Name = people.Name,
Age = people.Age
};
//以上写死了,只能为这两个类型服务
//采用反射:不同类型都可以实现,
{
var test = ReflectionMapper.Trans<People, PeopleCopy>(people);
}
{
//序列化器,
}
{
//通用,性能高
//能不能动态生成硬编码,缓存起来
//第一次执行时需要一定实际实现硬编码,然后存储在静态字典中
var result=ExpressionMapper.Trans<People, PeopleCopy>(people);
}
{
//第二次执行时效率很高,因为第一次已经实现了硬编码
var result = ExpressionMapper.Trans<People, PeopleCopy>(people);
}
{
//泛型缓存:第一次执行时需要通过表达式目录树构建委托
var result = ExpressionGenericMapper<People, PeopleCopy>.Trans(people);
}
{
//第二次进入的时候两个类型没有变化则直接返回委托,不需要再构建委托的过程
var result = ExpressionGenericMapper<People, PeopleCopy>.Trans(people);
}
//总结:表达式目录树动态生成的用途
//可以用来替代反射,因为反射可以通用,但是性能不够
//可以生成硬编码,可以提升性能
}
}
#endregion
}
public class People
{
public int Id;
public string Name { get; set; }
public int Age { get; set; }
}
public class PeopleCopy
{
public int Id;
public string Name { get; set; }
public int Age { get; set; }
}
/// <summary>
/// 反射匹配
/// </summary>
public class ReflectionMapper
{
/// <summary>
/// 利用反射匹配两个类的属性和字段
/// </summary>
/// <typeparam name="TIn"></typeparam>
/// <typeparam name="TOut"></typeparam>
/// <param name="tIn"></param>
/// <returns></returns>
public static TOut Trans<TIn,TOut>(TIn tIn)
{
TOut tOut = Activator.CreateInstance<TOut>();
//属性
foreach(var itemOut in tOut.GetType().GetProperties())
{
var propIn = tIn.GetType().GetProperty(itemOut.Name);
itemOut.SetValue(tOut, propIn.GetValue(tIn));
}
//字段
foreach(var itemOut in tOut.GetType().GetFields())
{
var propIn = tIn.GetType().GetField(itemOut.Name);
itemOut.SetValue(tOut, propIn.GetValue(tIn));
}
return tOut;
}
}
/// <summary>
/// 静态字典
/// </summary>
public class ExpressionMapper
{
//静态字典:全局唯一,静态字典缓存
private static Dictionary<string, object> _Dic = new Dictionary<string, object>();
public static TOut Trans<TIn,TOut>(TIn tIn)
{
string key = string.Format("funckey_{0}_{1}", typeof(TIn).FullName, typeof(TOut).FullName);
if(!_Dic.ContainsKey(key))
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingList = new List<MemberBinding>();
//绑定属性
foreach(var item in typeof(TOut).GetProperties())
{
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingList.Add(memberBinding);
}
//绑定字段
foreach(var item in typeof(TOut).GetFields())
{
MemberExpression field = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, field);
memberBindingList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
Func<TIn, TOut> func = lambda.Compile();//拼装是一次性的
_Dic[key] = func;
}
return ((Func<TIn, TOut>)_Dic[key]).Invoke(tIn);
}
}
/// <summary>
/// 泛型缓存:编译时确定
/// </summary>
/// <typeparam name="TIn"></typeparam>
/// <typeparam name="TOut"></typeparam>
public class ExpressionGenericMapper<TIn,TOut>
{
private static Func<TIn, TOut> _FUNC = null;
static ExpressionGenericMapper()
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingList = new List<MemberBinding>();
//绑定属性
foreach (var item in typeof(TOut).GetProperties())
{
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingList.Add(memberBinding);
}
//绑定字段
foreach (var item in typeof(TOut).GetFields())
{
MemberExpression field = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, field);
memberBindingList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
_FUNC = lambda.Compile();//拼装是一次性的
}
public static TOut Trans(TIn t)
{
return _FUNC(t);
}
}
}
第二堂课:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace 表达式目录树2
{
class Program
{
static void Main(string[] args)
{
Show();
Console.ReadKey();
}
private static int Get(int k)
{
return k * k;
}
public static void Show()
{
//ExpressionVisitor肯定是采用递归解析表达式目录树,因为不知道深度的一棵树
//只有一个入口叫Visit
//首先检查是个什么类型的表达式,然后调用对应的protect virtual visit方法
//得到结果继续去检查类型--调用对应的visit方法--再检查--再调用
//修改表达式目录树
{
Expression<Func<int, int, int>> exp = (m, n) => m * n + 2 + Get(5);
//修改为m*n-2
OperationsVisitor oVisitor = new OperationsVisitor();
Expression exp2 = oVisitor.Modify(exp);
}
//利用表达式目录树拼接Sql语句
{
var source = new List<People>().AsQueryable();//DbSet
var result=source.Where<People>(P => P.Age > 25);//SELECT * FROM People Where Age>25
Expression<Func<People, bool>> lambda = x => x.Age > 25;
ConditionBuilderVisitor visitor = new ConditionBuilderVisitor();
visitor.Visit(lambda);
Console.WriteLine(visitor.Condition());
}
{
//ORM 把数据库映射到程序内存,通过操作对象来完成数据库的管理
//屏蔽数据库,开发者完全不需要知道数据库
Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Id > 5
&& x.Name.StartsWith("1") && x.Name.EndsWith("1") && x.Name.Contains("1");
string sql = string.Format("Delete From [{0}] WHERE {1}",
typeof(People).Name, "[Age]>5 AND [ID]>5");
ConditionBuilderVisitor visitor = new ConditionBuilderVisitor();
visitor.Visit(lambda);
Console.WriteLine(visitor.Condition());
}
{
Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Name == "A" || x.Id > 5;
ConditionBuilderVisitor visitor = new ConditionBuilderVisitor();
visitor.Visit(lambda);
Console.WriteLine(visitor.Condition());
}
{
Expression<Func<People, bool>> lambda = x => x.Age > 5 || (x.Name == "A" && x.Id > 5);
ConditionBuilderVisitor visitor = new ConditionBuilderVisitor();
visitor.Visit(lambda);
Console.WriteLine(visitor.Condition());
}
{
Expression<Func<People, bool>> lambda = x => (x.Age > 5 || x.Name == "A") && x.Id > 5;
ConditionBuilderVisitor visitor = new ConditionBuilderVisitor();
visitor.Visit(lambda);
Console.WriteLine(visitor.Condition());
}
#region 表达式链接
{
Expression<Func<People, bool>> lambda1 = x => x.Age > 5;
Expression<Func<People, bool>> lambda2 = x => x.Id > 5;
Expression<Func<People, bool>> lambda3 = lambda1.And(lambda2);
Expression<Func<People, bool>> lambda4 = lambda1.Or(lambda2);
Expression<Func<People, bool>> lambda5 = lambda1.Not();
Do1(lambda3);
Do1(lambda4);
Do1(lambda5);
}
#endregion
}
private static void Do1(Func<People,bool> func)
{
List<People> people = new List<People>();
people.Where(func);
}
private static void Do1(Expression<Func<People,bool>> func)
{
List<People> people = new List<People>()
{
new People(){Id=4,Name="123",Age=4},
new People(){Id=5,Name="234",Age=5},
new People(){Id=6,Name="345",Age=6},
};
List<People> peopleList = people.Where(func.Compile()).ToList();
}
}
public class OperationsVisitor:ExpressionVisitor
{
public Expression Modify(Expression expression)
{
return base.Visit(expression);//调用父类的Visit方法
}
/// <summary>
/// 二元表达式
/// </summary>
/// <param name="b"></param>
/// <returns></returns>
protected override Expression VisitBinary(BinaryExpression b)
{
if(b.NodeType==ExpressionType.Add)
{
Expression left = base.Visit(b.Left);
Expression right = base.Visit(b.Right);
return Expression.Subtract(left, right);
}
return base.VisitBinary(b);
}
protected override Expression VisitConstant(ConstantExpression c)
{
return base.VisitConstant(c);
}
protected override Expression VisitParameter(ParameterExpression p)
{
return base.VisitParameter(p);
}
protected override Expression VisitMethodCall(MethodCallExpression m)
{
return base.VisitMethodCall(m);
}
}
public class People
{
public int Id;
public int Age { get; set; }
public string Name { get; set; }
}
public class ConditionBuilderVisitor:ExpressionVisitor
{
/// <summary>
/// 栈:先进后出
/// </summary>
private Stack<string> _StringStack = new Stack<string>();
public string Condition()
{
string condition = string.Concat(this._StringStack.ToArray());
this._StringStack.Clear();
return condition;
}
protected override Expression VisitBinary(BinaryExpression node)
{
this._StringStack.Push(")");
base.Visit(node.Right);
this._StringStack.Push(" " + node.NodeType.ToSqlOperator() + " ");
base.Visit(node.Left);
this._StringStack.Push("(");
return node;
}
protected override Expression VisitConstant(ConstantExpression node)
{
if (node == null) throw new AggregateException("ConstantExpression");
this._StringStack.Push("'" + node.Value + "'");
return node;
}
protected override Expression VisitMember(MemberExpression node)
{
if (node == null) throw new ArgumentNullException("MemberExpression");
this._StringStack.Push("[" + node.Member.Name + "]");
return node;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node == null) throw new ArgumentNullException("MethodCallExpression");
string format;
switch(node.Method.Name)
{
case "StartsWith":
format = "({0} LIKE {1}+'%')";
break;
case "Contains":
format = "({0} LIKE '%'+{1}+'%')";
break;
case "EndsWith":
format = "({0} LIKE '%'+{1})";
break;
default:
throw new Exception("不支持该方法");
}
this.Visit(node.Object);
this.Visit(node.Arguments);
string right = this._StringStack.Pop();
string left = this._StringStack.Pop();
this._StringStack.Push(String.Format(format, left, right));
return node;
}
}
internal static class SqlOperator
{
internal static string ToSqlOperator(this ExpressionType type)
{
switch (type)
{
case (ExpressionType.AndAlso):
case (ExpressionType.And):
return "AND";
case (ExpressionType.OrElse):
case (ExpressionType.Or):
return "OR";
case (ExpressionType.Not):
return "NOT";
case (ExpressionType.NotEqual):
return "<>";
case (ExpressionType.GreaterThan):
return ">";
case (ExpressionType.GreaterThanOrEqual):
return ">=";
case (ExpressionType.LessThan):
return "<";
case (ExpressionType.LessThanOrEqual):
return "<=";
case (ExpressionType.Equal):
return "=";
default:
throw new Exception("不支持该方法");
}
}
}
public static class ExpressionExtend
{
public static Expression<Func<T,bool>> And<T>(this Expression<Func<T,bool>> expr1,Expression<Func<T,bool>> expr2)
{
if (expr1 == null)
return expr2;
else if (expr2 == null)
return expr1;
ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
var left = visitor.Replace(expr1.Body);
var right = visitor.Replace(expr2.Body);
var body = Expression.And(left, right);
return Expression.Lambda<Func<T, bool>>(body, newParameter);
}
public static Expression<Func<T,bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
if (expr1 == null)
return expr2;
else if (expr2 == null)
return expr1;
ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
var left = visitor.Replace(expr1.Body);
var right = visitor.Replace(expr2.Body);
var body = Expression.Or(left, right);
return Expression.Lambda<Func<T, bool>>(body, newParameter);
}
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr)
{
if (expr == null)
return null;
var candidateExpr = expr.Parameters[0];
var body = Expression.Not(expr.Body);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
}
internal class NewExpressionVisitor:ExpressionVisitor
{
public ParameterExpression _NewParameter { get; private set; }
public NewExpressionVisitor(ParameterExpression parameter)
{
this._NewParameter = parameter;
}
public Expression Replace(Expression expression)
{
return this.Visit(expression);
}
protected override Expression VisitParameter(ParameterExpression node)
{
return this._NewParameter;
}
}
}