2015-09-04 25 views
5

Görsel bileşenlerin içerik doğrulamasını RTTI kullanarak Text-property ile genelleştirmeye çalışıyorum ancak bir dize değerini TRttiMethod.Invoke içine iletmeye çalıştığımda, "Geçersiz Typecast" mesajını alıyorum. (Aslında "Ungültige Typumwandlung" ama sanırım, bu uygun bir çeviri idi.)TRINKMethod.Invoke içinde bir dizeyi doğru olarak nasıl parametre olarak kullanırım?

Aşağıdaki kod, tüm geçilen nesnelerin mükemmel olduğu varsayılarak tüm güvenlik önlemlerinden, iddialardan ve benzerlerinden sıyrılıyor.

procedure ValidateTextFieldAndSetFocus(const Field: TObject; const Validator: TObject; const errorStates: array of TStringValidationResult; const sErrorMessage: string); 
var 
    context : TRttiContext; 
    objField : TRttiType; 
    objValid : TRttiType; 
    prop  : TRttiProperty; 
    execute : TRttiMethod; 
    I  : Integer; 
    validResult : TStringValidationResult; 
    value : TValue; 
begin 
    context := TRttiContext.Create; 
    objField := context.GetType(Field.ClassInfo); 
    objValid := context.GetType(Validator.ClassInfo); 
    prop  := objField.GetProperty('Text'); 
    value := prop.GetValue(Field); 
    execute := objValid.GetMethod('Execute'); 
    for I := 0 to High(errorStates) do 
    if execute.Invoke(Validator,[value]).TryAsType<TStringValidationResult>(validResult) then 
     if validResult = errorStates[I] then 
     begin 
     SetFocusIfCan(Field); 
     raise Exception.Create(sErrorMessage); 
     end; 
end; 

Validator'un Yürütme işlemi yalnızca bir dize Parametresine sahiptir. Dizelerin doğrudan TValue dizisine aktarıldığı örnekleri gördüm, ancak aynı yazım hatasıyla karşılaşıyorum.

düzenleme:

gerçek hata execute.Invoke(Validator,[value]) görünür.

Örnek

TNoSemicolonNullValidator = class 
    class function Execute(const aStr: string): TStringValidationResult; 
end; 

procedure TestValidation; 
var 
    Validator : TNoSemicolonNullValidator; 
begin 
    Validator := TNoSemicolonNullValidator.Create; 
    try 
    ValidateTextFieldAndSetFocus(Edit1,Validator,[svInvalid],'Edit1 is invalid!'); 
    finally 
    Validator.Free; 
    end; 
end; 
+0

verin bir [MCVE] yüzden –

+0

eksik parçalarını tahmin etmek zorunda değilsiniz Durduğu gibi, bu soru konu dışı olarak kapatılmalıdır. Çünkü bir çoğaltma sağlamadınız. Bunu düzelttikten sonra (yukarıdaki yorumdaki bağlantıya bakın), cevap verebiliriz. –

+0

Aslında kod, hatayı tespit etmek için yeterli bilgi sağlar. –

cevap

13

Burada bir sınıf işlevi aradığınız ama (non statik yöntemlerin gizli Öz argümanı) ilk parametre olarak bir TObject geçmektedir. Bir sınıf yönteminde, Self parametresi bir örnek olmamalı ve bunun sınıfı olmamalıdır. Yani doğru çağrı olacaktır: Burada

execute.Invoke(validator.ClassType, [value]); 

kanıtlamak için minimal bir örnektir:

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    Rtti, 
    SysUtils; 

type 
    TValidator = class 
    class function Execute(const s: string): Boolean; 
    end; 

class function TValidator.Execute(const s: string): Boolean; 
begin 
    Writeln(s); 
end; 

var 
    ctx: TRttiContext; 
    v: TValidator; 
begin 
    v := TValidator.Create; 
    try 
    ctx.GetType(TValidator).GetMethod('Execute').Invoke(v, ['test']); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    try 
    ctx.GetType(TValidator).GetMethod('Execute').Invoke(v.ClassType, ['test']); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 
İlgili konular