Extending the functions available to an expressionFlee allows you to extend the functions available for use in its expressions. Because of Flee's design, you are not required to define adapter classes or use delegates. You simply define your functions in a class or use the functions of an existing class and Flee will do the rest. Note that reflection is only used to lookup the functions when the expression is compiled. When the expression is evaluated, the functions are called using IL instructions just like in a compiled assembly.
The following is a guide to the various ways to add custom functions to an expression:
Importing public, static functionsDefine a class with all the public, static functions that you want to use:
public static class CustomFunctions
{
public static int Product(int a, int b)
{
return a * b;
}
public static int Sum(int a, int b)
{
return a + b;
}
}
Then use the Imports property of the ExpressionContext class to make them available for use in the expression:
ExpressionContext context = new ExpressionContext();
context.Imports.AddType(typeof(CustomFunctions));
context.Variables.Add("a", 100);
context.Variables.Add("b", 200);
IDynamicExpression e = context.CompileDynamic("product(a,b) + sum(a,b)");
int result = (int) e.Evaluate();
You can also import all the functions into a namespace:
context.Imports.AddType(typeof(CustomFunctions), "functions");
IDynamicExpression e = context.CompileDynamic("functions.product(a,b) + a - b");
This also works for the built-in .NET types:
ExpressionContext context = new ExpressionContext();
context.Imports.AddType(typeof(Math));
context.Variables.Add("a", 100);
IDynamicExpression e = context.CompileDynamic("cos(a)");
int result = (int) e.Evaluate();
Importing instance functions using variablesSince variables act as instances of their type, you can call any public, instance functions defined on them. Here's an example that demonstrates this:
ExpressionContext context = new ExpressionContext();
context.Variables.Add("rand", new Random());
IDynamicExpression e = context.CompileDynamic("rand.nextDouble() + 100");
double result = (double) e.Evaluate();
Importing function using an expression ownerWhen you attach an expression to an
expression owner, you can use any public/non-public static/instance functions on the owner class. The only limitation is that the functions cannot be put in a separate namespace. Here's the previous example, using the Random class as the expression owner:
Random rand = new Random();
ExpressionContext context = new ExpressionContext(rand);
IDynamicExpression e = context.CompileDynamic("nextDouble() + 100");
double result = (double) e.Evaluate();
Type-safetyFlee performs type-checking on the return type and parameters of all imported functions and will throw an ExpressionCompileException if either is not valid in the context of the expression. Flee will also not allow calls to functions that do not return a value.