2015-09-04 19 views
5

Tôi đang cố gắng khái quát xác nhận nội dung của các thành phần trực quan với thuộc tính Văn bản bằng RTTI nhưng khi tôi cố gắng chuyển giá trị chuỗi vào TRttiMethod.Invoke, tôi nhận được thông báo "Invalid Typecast". (Trên thực tế "Ungültige Typumwandlung" nhưng tôi đoán, đó là một bản dịch phù hợp.)Làm cách nào để sử dụng chuỗi trong TRttiMethod.Invoke làm thông số đúng?

Đoạn mã dưới đây bị tước bỏ tất cả các biện pháp an ninh, xác nhận và cứ như vậy.

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; 

Thực thi của Trình xác thực chỉ có một chuỗi Tham số. Tôi đã nhìn thấy các ví dụ trong đó các chuỗi được truyền trực tiếp vào mảng của TValue, nhưng sau đó tôi nhận được cùng một lỗi định kiểu.

chỉnh sửa:

Lỗi thực tế xuất hiện trong execute.Invoke(Validator,[value]).

Ví dụ

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

Vui lòng cung cấp một [mcve] để chúng ta không cần phải đoán những phần bị thiếu –

+0

Khi nó đứng, câu hỏi này nên được đóng lại như là tắt chủ đề. Bởi vì bạn đã không cung cấp một bản sao. Khi bạn khắc phục điều đó (xem liên kết trong nhận xét ở trên), chúng tôi sẽ có thể trả lời. –

+0

Trên thực tế, mã cung cấp đủ thông tin để phát hiện lỗi. –

Trả lời

13

Bạn đang kêu gọi một chức năng lớp ở đây nhưng bạn đang đi qua một TObject như tham số đầu tiên (đó là Tự luận ẩn của phương pháp không tĩnh). Trên một phương thức lớp, tham số Self không phải là một cá thể mà là một lớp của nó. Vì vậy, các cuộc gọi đúng sẽ là:

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

Dưới đây là một ví dụ nhỏ để chứng minh rằng:

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. 
Các vấn đề liên quan