-
Notifications
You must be signed in to change notification settings - Fork 123
Extending
Flee 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:
Define 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();
Since 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();
When 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();