1212namespace LinqKit ;
1313
1414/// <summary>
15- /// Extension methods for combining dynamic LINQ expressions with LinqKit's ExpressionStarter.
16- /// Provides fluent API for building complex predicates using string-based dynamic expressions.
15+ /// Provides dynamic predicate helpers for LinqKit predicates.
1716/// </summary>
1817public static class DynamicPredicateExtensions
1918{
2019 #region Methods
2120
2221 /// <summary>
23- /// Builds a dynamic predicate expression for the given property, operation, and value using System.Linq.Dynamic.Core.
24- /// Returns null if the property is not found or the value is invalid for the property type.
22+ /// Builds a dynamic predicate for a property filter.
2523 /// </summary>
26- /// <typeparam name="T">The entity type</typeparam>
27- /// <param name="propertyName">Property name or path (dot notation supported) </param>
28- /// <param name="operation">Operation to perform </param>
29- /// <param name="value">Value to compare </param>
30- /// <returns>Expression or null if not valid </returns>
24+ /// <typeparam name="T">Entity type. </typeparam>
25+ /// <param name="propertyName">Property name or dotted path. </param>
26+ /// <param name="operation">Filter operation. </param>
27+ /// <param name="value">Filter value. </param>
28+ /// <returns>A parsed predicate, or <see langword=" null"/> when invalid. </returns>
3129 private static Expression < Func < T , bool > > ? BuildDynamicExpression < T > ( string propertyName ,
3230 Ops operation , object ? value )
3331 {
@@ -62,119 +60,123 @@ public static class DynamicPredicateExtensions
6260 return lambda ;
6361 }
6462
65- /// <summary>
66- /// Combines the existing predicate with a new dynamic condition using AND logic.
67- /// If the dynamic expression is null or empty, the original predicate is returned unchanged.
68- /// Property name/path may be provided in camelCase, snake_case, kebab-case or mixed; each dotted segment is
69- /// normalized to PascalCase.
70- /// </summary>
71- /// <typeparam name="T">The type of the entity being queried</typeparam>
72- /// <param name="predicate">The existing expression starter to extend</param>
73- /// <param name="propertyName">
74- /// The name of the property to filter on. Supports nested properties using dot notation (e.g., "Address.City").
75- /// </param>
76- /// <param name="operation">
77- /// The comparison operation to perform (e.g., Equal, GreaterThan, Contains).
78- /// </param>
79- /// <param name="value">
80- /// The value to compare against. The type should match the property type.
81- /// </param>
82- /// <returns>
83- /// The extended <see cref="ExpressionStarter{T}" /> with the AND condition applied, or the original predicate if the
84- /// dynamic expression is null
85- /// </returns>
86- public static Expression < Func < T , bool > > DynamicAnd < T > ( this ExpressionStarter < T > predicate ,
87- string propertyName , Ops operation , object ? value )
88- {
89- var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
90- return dynamicExpression == null ? predicate : predicate . And ( dynamicExpression ) ;
91- }
92-
93- /// <summary>
94- /// Combines the existing predicate with a new dynamic condition using AND logic.
95- /// If the dynamic expression is null or empty, the original predicate is returned unchanged.
96- /// Property name/path may be provided in camelCase, snake_case, kebab-case or mixed; each dotted segment is
97- /// normalized to PascalCase.
98- /// </summary>
99- /// <typeparam name="T">The type of the entity being queried</typeparam>
100- /// <param name="predicate">The existing expression starter to extend</param>
101- /// <param name="propertyName">
102- /// The name of the property to filter on. Supports nested properties using dot notation (e.g., "Address.City").
103- /// </param>
104- /// <param name="operation">
105- /// The comparison operation to perform (e.g., Equal, GreaterThan, Contains).
106- /// </param>
107- /// <param name="value">
108- /// The value to compare against. The type should match the property type.
109- /// </param>
110- /// <returns>
111- /// The extended <see cref="ExpressionStarter{T}" /> with the AND condition applied, or the original predicate if the
112- /// dynamic expression is null
113- /// </returns>
114- public static Expression < Func < T , bool > > DynamicAnd < T > ( this Expression < Func < T , bool > > predicate ,
115- string propertyName , Ops operation , object ? value )
116- {
117- var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
118- return dynamicExpression == null ? predicate : predicate . And ( dynamicExpression ) ;
119- }
63+ #endregion
12064
121- /// <summary>
122- /// Combines the existing predicate with a new dynamic condition using OR logic.
123- /// If the dynamic expression is null or empty, the original predicate is returned unchanged.
124- /// Property name/path may be provided in camelCase, snake_case, kebab-case or mixed; each dotted segment is
125- /// normalized to PascalCase.
126- /// </summary>
127- /// <typeparam name="T">The type of the entity being queried</typeparam>
128- /// <param name="predicate">The existing expression starter to extend</param>
129- /// <param name="propertyName">
130- /// The name of the property to filter on. Supports nested properties using dot notation (e.g., "Address.City").
131- /// </param>
132- /// <param name="operation">
133- /// The comparison operation to perform (e.g., Equal, GreaterThan, Contains).
134- /// </param>
135- /// <param name="value">
136- /// The value to compare against. The type should match the property type.
137- /// </param>
138- /// <returns>
139- /// The extended <see cref="ExpressionStarter{T}" /> with the OR condition applied, or the original predicate if the
140- /// dynamic expression is null
141- /// </returns>
142- public static Expression < Func < T , bool > > DynamicOr < T > (
143- this ExpressionStarter < T > predicate ,
144- string propertyName , Ops operation , object ? value )
65+ extension < T > ( ExpressionStarter < T> predicate)
14566 {
146- var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
147- return dynamicExpression == null ? predicate : predicate . Or ( dynamicExpression ) ;
67+ /// <summary>
68+ /// Adds a dynamic condition using AND.
69+ /// </summary>
70+ /// <typeparam name="T">Entity type.</typeparam>
71+ /// <param name="propertyName">Property name or dotted path.</param>
72+ /// <param name="operation">Filter operation.</param>
73+ /// <param name="value">Filter value.</param>
74+ /// <returns>The combined predicate.</returns>
75+ public Expression < Func < T , bool > > DynamicAnd ( string propertyName , Ops operation , object ? value )
76+ {
77+ var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
78+ return dynamicExpression == null ? predicate : predicate . And ( dynamicExpression ) ;
79+ }
80+
81+ /// <summary>
82+ /// Adds a dynamic condition using OR.
83+ /// </summary>
84+ /// <typeparam name="T">Entity type.</typeparam>
85+ /// <param name="propertyName">Property name or dotted path.</param>
86+ /// <param name="operation">Filter operation.</param>
87+ /// <param name="value">Filter value.</param>
88+ /// <returns>The combined predicate.</returns>
89+ public Expression < Func < T , bool > > DynamicOr ( string propertyName , Ops operation , object ? value )
90+ {
91+ var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
92+ return dynamicExpression == null ? predicate : predicate . Or ( dynamicExpression ) ;
93+ }
94+
95+ /// <summary>
96+ /// Parses a dynamic LINQ expression and combines it using AND.
97+ /// </summary>
98+ /// <param name="expression">Dynamic LINQ expression.</param>
99+ /// <param name="values">Expression parameter values.</param>
100+ /// <returns>The combined predicate.</returns>
101+ public ExpressionStarter < T > DynamicAnd ( string expression ,
102+ params object ? [ ] values )
103+ {
104+ var dynamicExpr =
105+ DynamicExpressionParser . ParseLambda < T , bool > ( ParsingConfig . Default , false , expression , values ) ;
106+ return predicate . And ( dynamicExpr ) ;
107+ }
108+
109+ /// <summary>
110+ /// Parses a dynamic LINQ expression and combines it using OR.
111+ /// </summary>
112+ /// <param name="expression">Dynamic LINQ expression.</param>
113+ /// <param name="values">Expression parameter values.</param>
114+ /// <returns>The combined predicate.</returns>
115+ public ExpressionStarter < T > DynamicOr ( string expression ,
116+ params object ? [ ] values )
117+ {
118+ var dynamicExpr =
119+ DynamicExpressionParser . ParseLambda < T , bool > ( ParsingConfig . Default , false , expression , values ) ;
120+ return predicate . Or ( dynamicExpr ) ;
121+ }
148122 }
149123
150- /// <summary>
151- /// Combines the existing predicate with a new dynamic condition using OR logic.
152- /// If the dynamic expression is null or empty, the original predicate is returned unchanged.
153- /// Property name/path may be provided in camelCase, snake_case, kebab-case or mixed; each dotted segment is
154- /// normalized to PascalCase.
155- /// </summary>
156- /// <typeparam name="T">The type of the entity being queried</typeparam>
157- /// <param name="predicate">The existing expression starter to extend</param>
158- /// <param name="propertyName">
159- /// The name of the property to filter on. Supports nested properties using dot notation (e.g., "Address.City").
160- /// </param>
161- /// <param name="operation">
162- /// The comparison operation to perform (e.g., Equal, GreaterThan, Contains).
163- /// </param>
164- /// <param name="value">
165- /// The value to compare against. The type should match the property type.
166- /// </param>
167- /// <returns>
168- /// The extended <see cref="ExpressionStarter{T}" /> with the OR condition applied, or the original predicate if the
169- /// dynamic expression is null
170- /// </returns>
171- public static Expression < Func < T , bool > > DynamicOr < T > (
172- this Expression < Func < T , bool > > predicate ,
173- string propertyName , Ops operation , object ? value )
124+ extension < T > ( Expression < Func < T , bool > > predicate )
174125 {
175- var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
176- return dynamicExpression == null ? predicate : predicate . Or ( dynamicExpression ) ;
126+ /// <summary>
127+ /// Adds a dynamic condition using AND.
128+ /// </summary>
129+ /// <typeparam name="T">Entity type.</typeparam>
130+ /// <param name="propertyName">Property name or dotted path.</param>
131+ /// <param name="operation">Filter operation.</param>
132+ /// <param name="value">Filter value.</param>
133+ /// <returns>The combined predicate.</returns>
134+ public Expression < Func < T , bool > > DynamicAnd ( string propertyName , Ops operation , object ? value )
135+ {
136+ var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
137+ return dynamicExpression == null ? predicate : predicate . And ( dynamicExpression ) ;
138+ }
139+
140+ /// <summary>
141+ /// Adds a dynamic condition using OR.
142+ /// </summary>
143+ /// <typeparam name="T">Entity type.</typeparam>
144+ /// <param name="propertyName">Property name or dotted path.</param>
145+ /// <param name="operation">Filter operation.</param>
146+ /// <param name="value">Filter value.</param>
147+ /// <returns>The combined predicate.</returns>
148+ public Expression < Func < T , bool > > DynamicOr ( string propertyName , Ops operation , object ? value )
149+ {
150+ var dynamicExpression = BuildDynamicExpression < T > ( propertyName , operation , value ) ;
151+ return dynamicExpression == null ? predicate : predicate . Or ( dynamicExpression ) ;
152+ }
153+
154+ /// <summary>
155+ /// Parses a dynamic LINQ expression and combines it using AND.
156+ /// </summary>
157+ /// <param name="expression">Dynamic LINQ expression.</param>
158+ /// <param name="values">Expression parameter values.</param>
159+ /// <returns>The combined predicate.</returns>
160+ public ExpressionStarter < T > DynamicAnd ( string expression ,
161+ params object ? [ ] values )
162+ {
163+ var dynamicExpr =
164+ DynamicExpressionParser . ParseLambda < T , bool > ( ParsingConfig . Default , false , expression , values ) ;
165+ return predicate . And ( dynamicExpr ) ;
166+ }
167+
168+ /// <summary>
169+ /// Parses a dynamic LINQ expression and combines it using OR.
170+ /// </summary>
171+ /// <param name="expression">Dynamic LINQ expression.</param>
172+ /// <param name="values">Expression parameter values.</param>
173+ /// <returns>The combined predicate.</returns>
174+ public ExpressionStarter < T > DynamicOr ( string expression ,
175+ params object ? [ ] values )
176+ {
177+ var dynamicExpr =
178+ DynamicExpressionParser . ParseLambda < T , bool > ( ParsingConfig . Default , false , expression , values ) ;
179+ return predicate . Or ( dynamicExpr ) ;
180+ }
177181 }
178-
179- #endregion
180182}
0 commit comments