Exprelsior is a .NET Standard library that enables .NET developers to create strongly-typed binary lambda expressions from pure text using it's own query syntax or from the expression builder method.
With support to all major .NET data types, including nullable types, nested properties and it's own query syntax, Exprelsior brings the creation of dynamic predicates to a whole new level.
The objective of this library is to build binary lambda expressions in an dynamic manner.
Example:
Expression<Func<Foo, bool>> exp = t => t.Name == "Bar"; // Just a simple predicate
Building the above expression using the ExpressionBuilder.CreateBinary<T> method:
var exp = ExpressionBuilder.CreateBinary<Foo>("Name", "Bar", ExpressionOperator.Equal);
// result: t => t.Name == "Bar"
Building the above expression using the ExpressionBuilder.CreateBinaryFromQuery<T> method:
string query = "eq('Name', 'Bar')";
var exp = ExpressionBuilder.CreateBinaryFromQuery<Foo>(query);
// result: t => t.Name == "Bar"
Usages examples for generating dynamic lambda expressions.
[HttpGet]
public async Task<IActionResult> Get([FromQuery] string query)
{
// query = "gte('Age', '30')" (without double quotes)
var exp = ExpressionBuilder.CreateBinaryFromQuery<Foo>(query);
// exp = t => t.Age >= 30
var result = await FooRepository.GetAsync(predicate: exp);
return result;
}
[HttpGet]
public async Task<IActionResult> Get([FromQuery] int @operator, [FromQuery] string propertyName, [FromQuery] object value)
{
// @operator = 5 / property = Age / value = 30
var exp = ExpressionBuilder.CreateBinary<Foo>(propertyName, value, (ExpressionOperator)@operator);
// exp = t => t.Age >= 30
var result = await FooRepository.GetAsync(predicate: exp);
return result;
}
Query syntax description.
eq('Name', 'John')
operator(property, value)
cov('Name', ['John', 'Johnny', 'Mark', 'Myles', 'Alex'])
operator(property, [collection of values])
Operator: Describes which operation the query performs.
Property: The name of the property that the expression will compare. Supports nested properties.
Value/Collection Of Values: The effective value that the expression will compare the property with. It can be a single value or a collection of values.
Operator: First query element. No quotes. Precedes the opening parentheses.
Ex. "eq('Property', 'Value')".
Property: First query element inside de parenthesis. Surrounded by single quotes. Procedes the opening parentheses and precedes the comma separating this element from the value element. Consists of simple property name or dot-separated path to the property when nested.
Ex. "eq('Property', 'Value')".
Ex. "eq('Property.Property2.Property3', 'Value')".
Value (when single): Second query element inside the parentheses. Surrounded by single quotes. Procedes the comma separating this element from the property element and precedes the closing parenthesis. Consists of value representations.
Ex. "eq('Property', 'Value')".
Value (when multiple): Second query element inside the parentheses. Surrounded by square brackets. Procedes the comma separating this element from the property element and precedes the closing parenthesis. Consists of multiple value representations, each one surrounded by single quotes. Resembles an array.
Ex. "eq('Property', ['Value', 'Value2', 'Value3'])".
Simple queries are essentially translated to a single expression:
"eq('Property', 'Value')".
Gets translated to:
t => t.Property == Value
Exprelsior supports query composition, where multiple queries can be chained together, generating an composite expression.
"eq('Property', 'Value')+AND+gt('Property2', 'Value2')".
Gets translated to:
t => t.Property == Value && t.Property2 > Value2
Multiple levels of query composition are supported:
"eq('Property', 'Value')+AND+gt('Property2', 'Value2')+OR+cov('Property3', ['Value3', 'Value4', 'Value5'])".
Which gets translated to:
t => t.Property == Value && t.Property2 > Value2 || collection.Contains(t.Property3)
Compose Operator: Joins two queries together. Surrounded by plus signs. Procedes the previous query closing parentheses and precedes the next query first element.
Ex. "eq('Property', 'Value')+AND+ne('Property2', 'Value2')".
Exprelsior supports nested properties access.
"eq('Property.Property2', 'Value')"
Gets translated to:
t => t.Property.Property2 == value
This is specially useful for checking only the date or time part of a DateTime object:
"eq('DateTime.Date', '2019-12-31')"
Gets translated to something like:
t => t.DateTime.Date == DateTime(2019, 12, 31)
Exprelsior supports null values on the query syntax.
"eq('Property', '!$NULL$!')"
Gets translated to:
t => t.Property == null
Comprehensive list of the types and operators supported by Exprelsior.
Operator | Symbol | Query | Expression Builder |
---|---|---|---|
Equal | == | eq | ExpressionOperator.Equal |
Not Equal | != | ne | ExpressionOperator.NotEqual |
Less Than | < | lt | ExpressionOperator.LessThan |
Less Than Or Equal | <= | lte | ExpressionOperator.LessThanOrEqual |
Greater Than | > | gt | ExpressionOperator.GreaterThan |
Greater Than Or Equal | >= | gte | ExpressionOperator.GreaterThanOrEqual |
Contains | X => X.Contains(Y) | ct | ExpressionOperator.Contains |
Contains On Value | X => Y.Contains(X) | cov | ExpressionOperator.ContainsOnValue |
Starts With | X => X.StartsWith(Y) | sw | ExpressionOperator.StartsWith |
Ends With | X => X.EndsWith(Y) | ew | ExpressionOperator.EndsWith |
Operator | Symbol | Query | Expression Builder |
---|---|---|---|
And | && | +AND+ | fullExp = exp1.And(exp2) |
Or | || | +OR+ | fullExp = exp1.Or(exp2) |
Type | Supported | Signed/Unsigned | Nullable Support |
---|---|---|---|
string | ✅ | N/A | N/A |
bool | ✅ | N/A | ✅ |
char | ✅ | N/A | ✅ |
byte | ✅ | ✅ | ✅ |
short | ✅ | ✅ | ✅ |
int | ✅ | ✅ | ✅ |
long | ✅ | ✅ | ✅ |
float | ✅ | N/A | ✅ |
double | ✅ | N/A | ✅ |
decimal | ✅ | N/A | ✅ |
DateTime | ✅ | N/A | ✅ |
TimeSpan | ✅ | N/A | ✅ |
Value | Query | Expression Builder |
---|---|---|
null | !$NULL$! | null |