Building and evaluating expressions using Delphi RTTI

断了今生、忘了曾经 提交于 2019-12-10 12:18:58

问题


I am faced with a task of allowing the user to define the expressions using the 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 routine which will evaluate the animal with the supplied expression

function EvaluateAnimal(const animal : TAnimal; expression : string) : Double;
begin
  //Result :=  Turn expression to evaluation and give the result
end;

The user expression is (TAnimal.Weight * TAnimal.Height)/(TAnimal.Weight + TAnimal.Height)

Now, I can get the TAnimal using the RTTI Context and get the value of the animal's Height and Weight. However, how can i evaluate the expression what the user has supplied??

Is there any mechanism which i can use to prepare the user expression when my application starts and at runtime, just send the instance of animal to retrieve the value. The user is free to change the expression at anytime and the application has to evaluate the expression.

I am using Delphi XE3.


回答1:


You can use Live 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, I've intentionally omitted the code to free objects and so this code leaks. I chose to do that so we could concentrate on the expression evaluation aspect.



来源:https://stackoverflow.com/questions/16650447/building-and-evaluating-expressions-using-delphi-rtti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!