Delphi XE中动态表达式的应用 (调用自定义函数)

2017-07-13 19:46:27来源:CSDN作者:rocklee人点击

     最近发现除了用动态脚本语言来实现动态表达式的运算(比如fs),还可以在高版本的delphi里面实现 .

     如下代码, 先定义一个GetArea函数的实现(获得面积的函数), 然后注册它, 再利用ICompiledBinding来动态调用.

program Project1;{$APPTYPE CONSOLE}uses  System.Rtti,  System.Bindings.EvalProtocol,  System.Bindings.Evaluator,  System.Bindings.EvalSys,  System.Bindings.Methods,  System.Bindings.Consts,  System.SysUtils;function MakeMethodGetArea: IInvokable;begin  Result := MakeInvokable(function(Args: TArray<IValue>): IValue  var    lvP1,lvP2: IValue;  begin    if Length(Args) <> 2 then      raise EEvaluatorError.Create(Format(sUnexpectedArgCount, [2, Length(Args)]));    lvP1 := Args[0];    lvP2 := Args[1];    if lvP1.GetValue.IsEmpty  or lvP2.GetValue.IsEmpty then      Exit(TValueWrapper.Create(nil))    else      Exit(TValueWrapper.Create(lvP1.GetValue.AsExtended*lvP2.GetValue.AsExtended));  end);end;procedure DoIt;Var  LScope : IScope;  LCompiledExpr : ICompiledBinding;  LResult : TValue;  LDictionaryScope: TDictionaryScope;beginTBindingMethodsFactory.RegisterMethod(    TMethodDescription.Create(      MakeMethodGetArea,      'GetArea',      'GetArea', '', True,      'GetArea test function',      nil));  LScope:= TNestedScope.Create(BasicOperators, BasicConstants);  //add the registered methods  LScope := TNestedScope.Create(LScope, TBindingMethodsFactory.GetMethodScope);  LCompiledExpr:= Compile('GetArea(10,5)',LScope);  LResult:=LCompiledExpr.Evaluate(LScope, nil, nil).GetValue;  if not LResult.IsEmpty then    Writeln(LResult.ToString);end;begin try    DoIt; except    on E:Exception do        Writeln(E.Classname, ':', E.Message); end; Writeln('Press Enter to exit'); Readln;end.


那么在表达式里面引用自定义类怎么做呢, 非常简单:

{$APPTYPE CONSOLE} uses  System.Rtti,  System.TypInfo,  System.Bindings.Consts,  System.Bindings.EvalProtocol,  System.Bindings.Evaluator,  System.Bindings.EvalSys,  System.Bindings.ObjEval,  System.SysUtils; Type TMyClass= class  function Random(Value:Integer): Integer; end; { TMyClass }function TMyClass.Random(Value:Integer): Integer;begin  Result:=System.Random(Value);end; procedure DoIt;Var  LScope : IScope;  LCompiledExpr : ICompiledBinding;  LResult : TValue;  LDictionaryScope: TDictionaryScope;  M : TMyClass;begin  M := TMyClass.Create;  try    LScope:= TNestedScope.Create(BasicOperators, BasicConstants);    //add a object    LDictionaryScope := TDictionaryScope.Create;    LDictionaryScope.Map.Add('M', WrapObject(M));    LScope := TNestedScope.Create(LScope, LDictionaryScope);    LCompiledExpr:= Compile('M.Random(10000000)', LScope);    LResult:=LCompiledExpr.Evaluate(LScope, nil, nil).GetValue;    if not LResult.IsEmpty then      Writeln(LResult.ToString);  finally    M.Free;  end;end; begin try    Randomize;    DoIt; except    on E:Exception do        Writeln(E.Classname, ':', E.Message); end; Writeln('Press Enter to exit'); Readln;end.


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台