表达式目录树学习笔记
第一堂课:
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 ;
Expression< Func< int , int , int > > expression = ( m, n) = > m * n + 2 ;
int iResult1 = func. Invoke ( 12 , 12 ) ;
int iResult2 = expression. Compile ( ) . Invoke ( 12 , 12 ) ;
}
{
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 ) ;
}
{
ConstantExpression conLeft = Expression. Constant ( 345 ) ;
ConstantExpression conRight = Expression. Constant ( 456 ) ;
BinaryExpression binary = Expression. Add ( conLeft, conRight) ;
Expression< Action> actExpression = Expression. Lambda < Action > ( binary, null ) ;
actExpression. Compile ( ) ( ) ;
}
{
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 ) ) ;
}
{
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}%'" ;
}
}
IQueryable< int > list = null ;
if ( true )
{
Expression< Func< People, bool > > exp1 = x = > x. Id > 1 ;
}
if ( true )
{
Expression< Func< People, bool > > exp2 = x = > x. Age > 10 ;
}
Expression< Func< People, bool > > exp3 = x = > x. Id > 1 && x. Age > 10 ;
{
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 ; }
}
public class ReflectionMapper
{
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;
}
}
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) ;
}
}
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 ( )
{
{
Expression< Func< int , int , int > > exp = ( m, n) = > m * n + 2 + Get ( 5 ) ;
OperationsVisitor oVisitor = new OperationsVisitor ( ) ;
Expression exp2 = oVisitor. Modify ( exp) ;
}
{
var source = new List < People > ( ) . AsQueryable ( ) ;
var result= source. Where < People > ( P = > P. Age > 25 ) ;
Expression< Func< People, bool > > lambda = x = > x. Age > 25 ;
ConditionBuilderVisitor visitor = new ConditionBuilderVisitor ( ) ;
visitor. Visit ( lambda) ;
Console. WriteLine ( visitor. Condition ( ) ) ;
}
{
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) ;
}
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
{
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;
}
}
}