我面临的任务是允许用户使用已启用RTTI的已编译类来定义表达式。让我以简单的方式说明。
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;
我有一个例程,用所提供的表达式评估动物
function EvaluateAnimal(const animal : TAnimal; expression : string) : Double;
begin
//Result := Turn expression to evaluation and give the result
end;
用户表达式是
(TAnimal.Weight * TAnimal.Height)/(TAnimal.Weight + TAnimal.Height)
现在,我可以使用RTTI上下文获取TAnimal,并获得动物身高和体重的值。但是,我如何评估用户提供的表达式?
我的应用程序启动时是否可以使用任何机制来准备用户表达式,在运行时,只需发送动物实例来检索值。用户可以随时更改表达式,应用程序必须评估表达式。
我正在使用Delphi XE3。
答案 0 :(得分:2)
您可以使用Live Binding来评估表达式。这是一个简单的例子:
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.
注意,我故意省略了释放对象的代码,因此这段代码泄露了。我选择这样做,所以我们可以专注于表达评估方面。