How many times you needed a quick, simple method to create expressions in a
XML element value. and you wished there were an easy wy to create dynamic expressions at compile time as a literal
string to be compiled and evaluated at runtime using the same powerful
CLR. Well, I have!
The need for string expressions that can be simply expressed at compile time by engineers or non-engineering business or support team, has been a recurring theme through out my career. Whether its is business rules, business teams needs to modify it and change it frequently at runtime. or operation rules that devops team would like to control at runtime without the need to make a new deployment.
So, I rolled up my sleeves and created
XPress. It came handy in many situations and i used it in different product and solution. I had a few goals in mind when I designed
- Simple, yet powerful.
- Contained as possible, as little dependencies as possible.
- few to zero configurations.
- Purely written in C# and .net.
- Fast, and efficient.
- Generates an optimized cacheable .net expressions .
- Support all truth operators (
- Support basic data types
- Support variable binding at runtime.
- Ability to check on
How it works?
XPress is simple, all you have to do after installing XPress package using
nuget manager, is instantiating
XPress expressions, compile it, and execute it. here is a simple
XPress sample code:
As you can see,
XPress language doesn’t need much. very little configuration to start and you’re good to go. If you notice I used
XpressCompiler.Default a singleton compiler instance can be used quickly to compile expressions. But a compiler instance can be always instantiated through constructor.
The compiler class offers a single method
Compile(string) taking an xpress expression and return a compilation result. The
XpressCompilationResult object offers a boolean flag
Compiled to indicate the success or failure of the compilation process, and a
Log object of type
ILogReader which can be used to get status on compilation process and debug the result. a particularly useful pattern after compilation process is to check the
HasErrors fla, if true
GetErrorMessages() and print it or log it.
Finally, the compilation result object, will have a
Code predicate of type
Func<XpressRuntimeContext, bool> that is the optimized compiled .net expression tree for your string expression. it accepts
XpressRuntimeContext which is simply a strongly typed dictionary of
<string,string> to bind expression’s variables to runtime values. use the
XpressRuntimeContext object to pass values to your variables.
Code predicate jsut like any other .net
Func can be cached and executed multiple time. the result of execution is a
Variables literals can be used anywhere within an expression
The variable name follows same C# variable literals naming constraints. It Must start with a
_, and it may contain Unicode letter characters, decimal digit characters, Unicode connecting characters, Unicode combining characters, or Unicode formatting characters.
XPress supports boolean literals of
false values, numerical operands of
float decimal values, and
string operands. notice how the operand values are defined in the next sample code:
null operands can also be expressed to compare a string with nothing
% is supported on numerical operands
- operators applied to a
string operands it will act as
Note: Binary operators can’t be applied to mixed types of operands.
At the moment only unary logical operators are supported.
not can onyl be applied to
boolean operands or expressions.
Notice i applied
not to variable
x in the previous example. which is acceptable by
XPress compiler. it will assume that value of
x will be boolean at runtime otherwise it will throw a runtime exception.
The following relational expressions are supported:
geGreater Than or Equal
leLess Than or Equal
The real power of
XPress is composition, you can compose powerful expressions using conditional logical
- Unary Logial Operators:
- Binary Multiplicative Operators:
- Binary Additive Operators:
- Equality Operators:
- Logical Operators:
XPressis very powerful and can be used to compose sophisticated boolean expressions as strings.
What about performance?
XPress is built to be fast and optimized to generated very efficient .net lambda expressions. the most expensive part of the process as you can expect is the compilation of expressions, but this phase needs to occur once, and the result can be cached for the lifetime of the application. on average
Xpress compilation phase takes about ~120ms.
Find more information about
XPress on project github repository. I will be blogging more in the future about the internals implementation of the language and its compiler.