2013-05-20 6 views
0

사용자가 RTTI를 사용하는 컴파일 된 클래스를 사용하여 표현식을 정의 할 수 있도록 허용하는 작업에 직면했습니다. 간단한 방식으로 설명하겠습니다.Delphi 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; 

사용자 발현 내가 RTTI 컨텍스트를 사용하여 TAnimal를 얻을 수 있습니다, 지금 (TAnimal.Weight * TAnimal.Height)/(TAnimal.Weight + TAnimal.Height)

이며, 동물의 키와 몸무게의 가치를 얻으십시오. 그러나, 어떻게 사용자가 제공 한 표현을 평가할 수 있습니까 ??

내 응용 프로그램이 시작될 때 런타임에 사용자 표현을 준비하는 데 사용할 수있는 메커니즘이 있습니까? 그냥 animal 인스턴스를 보내 값을 검색하십시오. 사용자는 언제든지 표현식을 자유롭게 변경할 수 있으며 응용 프로그램은 표현식을 평가해야합니다.

저는 Delphi XE3을 사용하고 있습니다.

+0

이 경우 JclExprEval을 사용합니다. 또한 속성은 인스턴스 속성이며 클래스 속성이 아닙니다. –

+0

수학 파서의 경우 [델파이의 수학 표현 파서 (mathematical expression parser)] (http://stackoverflow.com/q/1326258/576719)를 참조하십시오. 표현의 복잡성에 따라 스크립팅 언어를 사용할 수 있습니다. ['Delphi 용 스크립팅 라이브러리] (http://stackoverflow.com/q/226135/576719)를 참조하십시오. –

+0

@LURD 그러나 스크립팅 라이브러리를 사용하면 성능 병목 현상이 발생합니까 ?? 표현식이 항상 파싱되는 것처럼. –

답변

2

라이브 바인딩을 사용하여 표현식을 평가할 수 있습니다. 여기에 사소한 예는 다음과 같습니다

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. 

주, 나는 의도적으로 무료 객체에 코드를 생략하고 있으므로이 코드를 유출했습니다. 우리가 표현 평가 측면에 집중할 수 있도록하기로 결정했습니다.

+0

라인 expr.Evaluate, 표현식을 다시 구문 분석하려고합니까 아니면 임의의 코드 스택으로 컴파일되고 평가됩니까? 그 이유는 거의 실시간 처리를 통해 같은 종류의 많은 객체에 대해 표현식을 평가해야하기 때문입니다. 어쨌든, 나는 당신이 제안한 것과 같은 행을 따라 갈 것이며 성과를 점검 할 것입니다. –

+0

표현식은'CreateUnmanagedBinding'을 호출하여 컴파일됩니다. 실행 가능한 코드로 컴파일되지 않으며, 단지 표현식의 중간 표현이 평가됩니다. –