11using System ;
2- using System . Linq ;
2+ using System . Collections . ObjectModel ;
33using System . Linq . Expressions ;
4+ using JetBrains . Annotations ;
45
56namespace Abp . Linq . Expressions
67{
8+ // Codes below are taken from https://github.com/scottksmith95/LINQKit project.
9+
10+ /// <summary> The Predicate Operator </summary>
11+ internal enum PredicateOperator
12+ {
13+ /// <summary> The "Or" </summary>
14+ Or ,
15+
16+ /// <summary> The "And" </summary>
17+ And
18+ }
19+
20+ /// <summary>
21+ /// See http://www.albahari.com/expressions for information and examples.
22+ /// </summary>
723 internal static class PredicateBuilder
824 {
9- public static Expression < Func < T , bool > > True < T > ( ) { return f => true ; }
25+ private class RebindParameterVisitor : ExpressionVisitor
26+ {
27+ private readonly ParameterExpression _oldParameter ;
28+ private readonly ParameterExpression _newParameter ;
29+
30+ public RebindParameterVisitor ( ParameterExpression oldParameter , ParameterExpression newParameter )
31+ {
32+ _oldParameter = oldParameter ;
33+ _newParameter = newParameter ;
34+ }
35+
36+ protected override Expression VisitParameter ( ParameterExpression node )
37+ {
38+ if ( node == _oldParameter )
39+ {
40+ return _newParameter ;
41+ }
42+
43+ return base . VisitParameter ( node ) ;
44+ }
45+ }
46+
47+ /// <summary> Start an expression </summary>
48+ public static ExpressionStarter < T > New < T > ( Expression < Func < T , bool > > expr = null ) { return new ExpressionStarter < T > ( expr ) ; }
49+
50+ /// <summary> Create an expression with a stub expression true or false to use when the expression is not yet started. </summary>
51+ public static ExpressionStarter < T > New < T > ( bool defaultExpression ) { return new ExpressionStarter < T > ( defaultExpression ) ; }
52+
53+ /// <summary> Always true </summary>
54+ [ Obsolete ( "Use PredicateBuilder.New() instead." ) ]
55+ public static Expression < Func < T , bool > > True < T > ( ) { return new ExpressionStarter < T > ( true ) ; }
56+
57+ /// <summary> Always false </summary>
58+ [ Obsolete ( "Use PredicateBuilder.New() instead." ) ]
59+ public static Expression < Func < T , bool > > False < T > ( ) { return new ExpressionStarter < T > ( false ) ; }
60+
61+ /// <summary> OR </summary>
62+ public static Expression < Func < T , bool > > Or < T > ( [ NotNull ] this Expression < Func < T , bool > > expr1 , [ NotNull ] Expression < Func < T , bool > > expr2 )
63+ {
64+ var expr2Body = new RebindParameterVisitor ( expr2 . Parameters [ 0 ] , expr1 . Parameters [ 0 ] ) . Visit ( expr2 . Body ) ;
65+ return Expression . Lambda < Func < T , bool > > ( Expression . OrElse ( expr1 . Body , expr2Body ) , expr1 . Parameters ) ;
66+ }
67+
68+ /// <summary> AND </summary>
69+ public static Expression < Func < T , bool > > And < T > ( [ NotNull ] this Expression < Func < T , bool > > expr1 , [ NotNull ] Expression < Func < T , bool > > expr2 )
70+ {
71+ var expr2Body = new RebindParameterVisitor ( expr2 . Parameters [ 0 ] , expr1 . Parameters [ 0 ] ) . Visit ( expr2 . Body ) ;
72+ return Expression . Lambda < Func < T , bool > > ( Expression . AndAlso ( expr1 . Body , expr2Body ) , expr1 . Parameters ) ;
73+ }
74+
75+ /// <summary>
76+ /// Extends the specified source Predicate with another Predicate and the specified PredicateOperator.
77+ /// </summary>
78+ /// <typeparam name="T">The type</typeparam>
79+ /// <param name="first">The source Predicate.</param>
80+ /// <param name="second">The second Predicate.</param>
81+ /// <param name="operator">The Operator (can be "And" or "Or").</param>
82+ /// <returns>Expression{Func{T, bool}}</returns>
83+ public static Expression < Func < T , bool > > Extend < T > ( [ NotNull ] this Expression < Func < T , bool > > first , [ NotNull ] Expression < Func < T , bool > > second , PredicateOperator @operator = PredicateOperator . Or )
84+ {
85+ return @operator == PredicateOperator . Or ? first . Or ( second ) : first . And ( second ) ;
86+ }
87+
88+ /// <summary>
89+ /// Extends the specified source Predicate with another Predicate and the specified PredicateOperator.
90+ /// </summary>
91+ /// <typeparam name="T">The type</typeparam>
92+ /// <param name="first">The source Predicate.</param>
93+ /// <param name="second">The second Predicate.</param>
94+ /// <param name="operator">The Operator (can be "And" or "Or").</param>
95+ /// <returns>Expression{Func{T, bool}}</returns>
96+ public static Expression < Func < T , bool > > Extend < T > ( [ NotNull ] this ExpressionStarter < T > first , [ NotNull ] Expression < Func < T , bool > > second , PredicateOperator @operator = PredicateOperator . Or )
97+ {
98+ return @operator == PredicateOperator . Or ? first . Or ( second ) : first . And ( second ) ;
99+ }
100+ }
101+
102+ /// <summary>
103+ /// ExpressionStarter{T} which eliminates the default 1=0 or 1=1 stub expressions
104+ /// </summary>
105+ /// <typeparam name="T">The type</typeparam>
106+ public class ExpressionStarter < T >
107+ {
108+ internal ExpressionStarter ( ) : this ( false ) { }
109+
110+ internal ExpressionStarter ( bool defaultExpression )
111+ {
112+ if ( defaultExpression )
113+ DefaultExpression = f => true ;
114+ else
115+ DefaultExpression = f => false ;
116+ }
117+
118+ internal ExpressionStarter ( Expression < Func < T , bool > > exp ) : this ( false )
119+ {
120+ _predicate = exp ;
121+ }
10122
11- public static Expression < Func < T , bool > > False < T > ( ) { return f => false ; }
123+ /// <summary>The actual Predicate. It can only be set by calling Start.</summary>
124+ private Expression < Func < T , bool > > Predicate => ( IsStarted || ! UseDefaultExpression ) ? _predicate : DefaultExpression ;
12125
13- public static Expression < Func < T , bool > > Or < T > ( this Expression < Func < T , bool > > expr1 , Expression < Func < T , bool > > expr2 )
126+ private Expression < Func < T , bool > > _predicate ;
127+
128+ /// <summary>Determines if the predicate is started.</summary>
129+ public bool IsStarted => _predicate != null ;
130+
131+ /// <summary> A default expression to use only when the expression is null </summary>
132+ public bool UseDefaultExpression => DefaultExpression != null ;
133+
134+ /// <summary>The default expression</summary>
135+ public Expression < Func < T , bool > > DefaultExpression { get ; set ; }
136+
137+ /// <summary>Set the Expression predicate</summary>
138+ /// <param name="exp">The first expression</param>
139+ public Expression < Func < T , bool > > Start ( Expression < Func < T , bool > > exp )
140+ {
141+ if ( IsStarted )
142+ throw new Exception ( "Predicate cannot be started again." ) ;
143+
144+ return _predicate = exp ;
145+ }
146+
147+ /// <summary>Or</summary>
148+ public Expression < Func < T , bool > > Or ( [ NotNull ] Expression < Func < T , bool > > expr2 )
149+ {
150+ return ( IsStarted ) ? _predicate = Predicate . Or ( expr2 ) : Start ( expr2 ) ;
151+ }
152+
153+ /// <summary>And</summary>
154+ public Expression < Func < T , bool > > And ( [ NotNull ] Expression < Func < T , bool > > expr2 )
14155 {
15- var invokedExpr = Expression . Invoke ( expr2 , expr1 . Parameters . Cast < Expression > ( ) ) ;
156+ return ( IsStarted ) ? _predicate = Predicate . And ( expr2 ) : Start ( expr2 ) ;
157+ }
16158
17- return Expression . Lambda < Func < T , bool > > ( Expression . OrElse ( expr1 . Body , invokedExpr ) , expr1 . Parameters ) ;
159+ /// <summary> Show predicate string </summary>
160+ public override string ToString ( )
161+ {
162+ return Predicate == null ? null : Predicate . ToString ( ) ;
18163 }
19164
20- public static Expression < Func < T , bool > > And < T > ( this Expression < Func < T , bool > > expr1 , Expression < Func < T , bool > > expr2 )
165+ #region Implicit Operators
166+ /// <summary>
167+ /// Allows this object to be implicitely converted to an Expression{Func{T, bool}}.
168+ /// </summary>
169+ /// <param name="right"></param>
170+ public static implicit operator Expression < Func < T , bool > > ( ExpressionStarter < T > right )
21171 {
22- var invokedExpr = Expression . Invoke ( expr2 , expr1 . Parameters . Cast < Expression > ( ) ) ;
172+ return right == null ? null : right . Predicate ;
173+ }
23174
24- return Expression . Lambda < Func < T , bool > > ( Expression . AndAlso ( expr1 . Body , invokedExpr ) , expr1 . Parameters ) ;
175+ /// <summary>
176+ /// Allows this object to be implicitely converted to an Expression{Func{T, bool}}.
177+ /// </summary>
178+ /// <param name="right"></param>
179+ public static implicit operator Func < T , bool > ( ExpressionStarter < T > right )
180+ {
181+ return right == null ? null : ( right . IsStarted || right . UseDefaultExpression ) ? right . Predicate . Compile ( ) : null ;
182+ }
183+
184+ /// <summary>
185+ /// Allows this object to be implicitely converted to an Expression{Func{T, bool}}.
186+ /// </summary>
187+ /// <param name="right"></param>
188+ public static implicit operator ExpressionStarter < T > ( Expression < Func < T , bool > > right )
189+ {
190+ return right == null ? null : new ExpressionStarter < T > ( right ) ;
25191 }
192+ #endregion
193+
194+ #region Implement Expression<TDelagate> methods and properties
195+ #if ! ( NET35 )
196+
197+ /// <summary></summary>
198+ public Func < T , bool > Compile ( ) { return Predicate . Compile ( ) ; }
199+ #endif
200+
201+ #if ! ( NET35 || WINDOWS_APP || NETSTANDARD || PORTABLE || PORTABLE40 || UAP )
202+ /// <summary></summary>
203+ public Func < T , bool > Compile ( DebugInfoGenerator debugInfoGenerator ) { return Predicate . Compile ( debugInfoGenerator ) ; }
204+
205+ /// <summary></summary>
206+ public Expression < Func < T , bool > > Update ( Expression body , IEnumerable < ParameterExpression > parameters ) { return Predicate . Update ( body , parameters ) ; }
207+ #endif
208+ #endregion
209+
210+ #region Implement LamdaExpression methods and properties
211+
212+ /// <summary></summary>
213+ public Expression Body => Predicate . Body ;
214+
215+
216+ /// <summary></summary>
217+ public ExpressionType NodeType => Predicate . NodeType ;
218+
219+ /// <summary></summary>
220+ public ReadOnlyCollection < ParameterExpression > Parameters => Predicate . Parameters ;
221+
222+ /// <summary></summary>
223+ public Type Type => Predicate . Type ;
224+
225+ #if ! ( NET35 )
226+ /// <summary></summary>
227+ public string Name => Predicate . Name ;
228+
229+ /// <summary></summary>
230+ public Type ReturnType => Predicate . ReturnType ;
231+
232+ /// <summary></summary>
233+ public bool TailCall => Predicate . TailCall ;
234+ #endif
235+
236+ #if ! ( NET35 || WINDOWS_APP || NETSTANDARD || PORTABLE || PORTABLE40 || UAP )
237+ /// <summary></summary>
238+ public void CompileToMethod ( MethodBuilder method ) { Predicate . CompileToMethod ( method ) ; }
239+
240+ /// <summary></summary>
241+ public void CompileToMethod ( MethodBuilder method , DebugInfoGenerator debugInfoGenerator ) { Predicate . CompileToMethod ( method , debugInfoGenerator ) ; }
242+
243+ #endif
244+ #endregion
245+
246+ #region Implement Expression methods and properties
247+ #if ! ( NET35 )
248+ /// <summary></summary>
249+ public virtual bool CanReduce => Predicate . CanReduce ;
250+ #endif
251+ #endregion
26252 }
27253}
0 commit comments