Non-official collection of solutions and examples for this new programming language, from a host perspective. Primarily written for my own benefit, but hopefully helpful to someone else as well.
Compile time checks for syntax errors, unknown symbols, and other possible errors. Some good test cases for CheckResult can be found here. The following is the simplest way to verify if an expression is valid:
var expression = "1 + 2"; // Some Power Fx expression
var engine = new RecalcEngine(config);
var checkResult = engine.Check(expression);
if (checkResult.IsSuccess)
{
// Expression is valid.
}
The engine.Check()
method accepts some arguments:
Coming soon.
Runtime evaluates a Power Fx expression and returns a result value (FormulaValue). The following is the simplest way to verify if an expression is valid:
var expression = "1 + 2"; // Some Power Fx expression
var engine = new RecalcEngine(config);
var result = engine.Eval(expression); // Returns a FormulaValue derived object if the expression is valid.
The engine.Eval()
method accepts some arguments:
Coming soon.
Symbols are variables (locals, globals), enums, options sets, and functions provided to the engine. They are mutable to support sessionful scenarios and can be chained together.
- SymbolsTable: Stores variable definitions (names and their types). This feeds functions, variables, enums, etc into the binder. Check these test cases for reference.
- SymbolsValue: Runtime values corresponding to static values described in a SymbolTable. Check these other test cases for reference.
Some common tricks with Symbols:
- Compose symbols: It is possible to combine two or more symbol objects into a single one. This can be done by calling
ReadOnlySymbolTable.Compose
(test case) orReadOnlySymbolValues.Compose
(test case) methods. - Add services: Coming soon.
- Add/Remove functions: Coming soon.
Hosts can add low-code customized functions to the engine:
Example: ApplyDiscount(price:Decimal,perc:Decimal):Decimal = price * (1 - perc / 100);
var udfScript = "ApplyDiscount(price:Decimal,perc:Decimal):Decimal = price * (1 - perc / 100);";
var recalcEngine = new RecalcEngine();
recalcEngine.AddUserDefinedFunction(udfScript, CultureInfo.InvariantCulture);
// Other engine configuration code
var newPrice = recalcEngine.Eval("ApplyDiscount(item.Price, 10)");
Let's break down the above user-defined function:
ApplyDiscount
is the user-defined function name.(price:Decimal,perc:Decimal)
declares all the function's arguments. The syntax is(arg_name:arg_type)
.:Decimal
is the function return type.price * (1 - perc / 100)
user-defined function implementation.;
makes it possible to declare multiple user-defined functions at once.
These test cases will give a good understanding of user-defined functions capabilities.
Error message translation can be done by specifying the desired locale to the PowerFxConfig object:
var config_ptBR = new PowerFxConfig(CultureInfo.GetCultureInfo("pt-BR"));
var engine = new Engine(config_ptBR);
Then check if an expression is valid:
var check = engine.Check("7E1111111");
check.Errors.Dump(); // Error 0-9: O valor numérico é grande demais.
If you need to log which expressions are being executed but want to keep any identifier/values private (for audit purposes for example), call CheckResult.ApplyGetLogging() instance method.
var engine = new Engine(new PowerFxConfig());
var check = engine.Check(myValue.ToExpression());
// Set(#$firstname$#, #$number$# + #$number$#)#$error$#Launch(#$string$#, #$firstname$#.#$righthandid$#, Parent.#$righthandid$#)
check.ApplyGetLogging();
Please note that check.ApplyGetLogging()
can produce different results depending if binding has been applied or not.
Power Fx offers a simple way to serialize and deserialize FormulaValue values. To serialize, call the "ToExpression()" method on any FormulaValue derived types (StringValue, NumberValue, etc) to get a serialized value version.
var myValue = FormulaValue.New(100);
myValue.ToExpression().Dump(); // "100"
To deserialize, call Eval to rehydrate the previously serialized value back to a FormulaValue.
var myValue = FormulaValue.New(100);
var engine = new Engine(new PowerFxConfig());
var check = engine.Check(myValue.ToExpression());
var result = check.GetEvaluator().Eval();
result.ToObject(); // 100
Coming soon.
The following is a list of references to test different cases: