2011-03-25 38 views
4

如何使用RTTI設置枚舉字段的值?枚舉的Delphi RTTI SetValue

I.e.

type 
    TCPIFileStatus= (fsUnknown, fsProcessed); 
    TTest = class 
    FStatus: TCPIFileStatus; 
    end; 
     ... 
    var 
    Data: TTest; 
    Ctx: TRttiContext; 
    Status : TCPIFileStatus; 
    begin 
    Data := TTest.Create; 
    Status := fsProcessed; 
    Ctx.GetType(Data.ClassType).GetField('FStatus').SetValue(Data, Status); 
    end; 

我得到 「無效的類類型轉換。」
注意:我需要使用RTTI,因爲在設計時我不會總是知道對象類型或字段名稱。

回答

6

你必須通過一個TValueSetValue方法嘗試使用此代碼:

{$APPTYPE CONSOLE} 
uses 
    Rtti, 
    SysUtils; 


type 
    TCPIFileStatus= (fsUnknown, fsProcessed); 
    TTest = class 
    FStatus: TCPIFileStatus; 
    end; 

    var 
    Data : TTest; 
    Ctx : TRttiContext; 
    Status : TCPIFileStatus; 
    v  : TValue; 
begin 
    try 
    Data := TTest.Create; 
    try 
     Status := fsProcessed; 
     v:= v.From(status); 
     Ctx.GetType(Data.ClassType).GetField('FStatus').SetValue(Data, v); 

     // do your stuff 
    finally 
     Data.Free; 
    end; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 
+0

謝謝,我看過FromVariant和FromOrdinal,錯過了From方法。 – 2011-03-25 03:29:28

0

使用TValue.From通用的方法來獲取兼容TValue值傳遞給SetValue方法...

嗯...很難從話得到更好的代碼:

type 
    TCPIFileStatus= (fsUnknown, fsProcessed); 
    TTest = class 
    FStatus: TCPIFileStatus; 
    end; 

procedure TForm2.Button1Click(Sender: TObject); 
var 
    Data: TTest; 
    Ctx: TRttiContext; 
    Status : TCPIFileStatus; 
    AValue: TValue; 
begin 
    Data := TTest.Create; 
    try 
    Status := fsProcessed; 
    Ctx.GetType(Data.ClassType).GetField('FStatus').SetValue(Data, TValue.From(Status)); 
    Assert(Data.FStatus = Status, 'Something wrong on assigning status trough RTTI!'); 
    finally 
    Data.Free; 
    end; 
end; 
1

另一種解決這個問題,在如果你不知道確切的枚舉類型上你的函數,但它是TypeInfo,就是使用TValue的Make過程。

procedure Make(AValue: NativeInt; ATypeInfo: PTypeInfo; out Result: TValue); overload; static; 

下面是一個例子(從XML解析器配置): 這是後來用於TRTTIField/TRTTIProperty.SetValue()

function EnumNameToTValue(Name: string; EnumType: PTypeInfo): TValue; 
var 
    V: integer; 

begin 
    V:= GetEnumValue(EnumType, Name); 
    TValue.Make(V, EnumType, Result); 
end; 

希望這有助於你。