Building and Evaluating Expressions Using Delphi RTTI
I faced the challenge of allowing the user to define expressions using compiled classes with RTTI enabled. Let me put it in a simple way.
TAnimal = class(TPersistent)
private
fWeight : Double;
fHeight : Double;
fName : string;
published
property Weight : Double read fWeight write fWeight;
property Height : Double read fHeight write fHeight;
property Name : string read fName write fName;
end;
And I have a procedure that will evaluate an animal with the provided expression
function EvaluateAnimal(const animal : TAnimal; expression : string) : Double;
begin
//Result := Turn expression to evaluation and give the result
end;
Custom expression
(TAnimal.Weight * TAnimal.Height)/(TAnimal.Weight + TAnimal.Height)
Now I can get TAnimal using RTTI Context and get the animal's Height and Weight. However, how can I evaluate the expression the user provided?
Is there any mechanism I can use to prepare a custom expression when my app starts and at runtime, just send an animal instance to get the value. The user is free to change the expression at any time, and the application must evaluate the expression.
I am using Delphi XE3.
source to share
You can use direct bindings to evaluate expressions. Here's a trivial example:
program BindingsDemo;
{$APPTYPE CONSOLE}
uses
System.Rtti,
System.Bindings.Expression,
System.Bindings.EvalProtocol,
System.Bindings.Helper;
type
TFoo = class
Val1: Integer;
Val2: Integer;
Result: TValue;
end;
procedure Main;
var
Foo: TFoo;
scope: IScope;
expr: TBindingExpression;
begin
Foo := TFoo.Create;
Foo.Val1 := 42;
Foo.Val2 := 666;
scope := TBindings.CreateAssociationScope([Associate(Foo, 'Foo')]);
expr := TBindings.CreateUnmanagedBinding(
[Scope],
'Foo.Val1 + Foo.Val2',
[Scope],
'Foo.Result',
nil
);
expr.Evaluate;
Assert(Foo.Result.AsInteger=708);
Writeln(Foo.Result.ToString);
end;
begin
Main;
Readln;
end.
Note that I intentionally left out the code for free objects, and therefore this code is leaking. I decided to do this so that we can focus on the evaluation aspect of the expression.
source to share