2013-07-17 38 views
8

Trong các loại sau đây:Delphi - tên Extract setter phương pháp của một tài sản

MyClass = class(TInterfacedPersistent) 
private 
    FMyProperty: Integer;  
published 
    procedure setMyProperty(Value: Integer); virtual; 
    property MyProperty: Integer read FMyProperty write setMyProperty; 

Tôi muốn biết tên của phương pháp setter của "myProperty" bất động sản qua RTTI. Tôi đã thử các cách sau:

procedure ShowSetterMethodsNames(pMyObject: TObject); 
    var 
     vPropList: TPropList;  
     vCount, I: Integer; 
    begin 
     vCount:= GetPropList(pMyObject.ClassInfo, tkProperties, @vPropList); 

     for I:= 0 to vCount -1 do 
     begin 
      if Assigned(vPropList[I]^.SetProc) then 
      ShowMessage(pMyObject.ClassType.MethodName(vPropList[I]^.SetProc)); 
     end; 
    end; 

Mặc dù con trỏ không phải là nil, tất cả những gì tôi có là thư trống. Có ai có một số mẹo cho tôi không?

P .: Tôi đang sử dụng Delphi XE4, và tôi biết tôi nên sử dụng RTTI mở rộng thay vì cổ điển, nhưng dù sao, tôi không thể làm những gì tôi muốn trong cả hai tính năng ... Vì vậy, bất kỳ trợ giúp sẽ được đánh giá cao. Cảm ơn bạn đã trả lời.


EDITION CUỐI CÙNG, vấn đề giải quyết:

Đây là mã làm việc, có trụ sở tại (giúp đỡ của bạn bè của tôi và ...) RTTI đơn vị (phương pháp DoSetValue của lớp TRTTIInstanceProperty):

procedure ShowVirtualSettersNames(pObject: Pointer); 
var 
    vSetter, vPointer: Pointer; 
    vPropList: TArray<TRttiProperty>; 
    vProp: TRttiProperty; 
begin 
    vPropList:= RTTIUtils.ExtractProperties(TObject(pObject).ClassType); // Helper to get properties from a type, based in extended RTTI 

    for vProp in vPropList do 
    begin 
    vPointer:= TRttiInstanceProperty(vProp).PropInfo^.SetProc; 
    vPointer:= PPointer(PInteger(pObject)^ + Smallint(vPointer))^;  
    ShowMessage(TObject(pObject).ClassType.MethodName(vPointer)); 
    end; 
end; 

CHỈ CÓ CÔNG TRÌNH ĐỐI VỚI BỘ LỆNH VIRTUAL, đối với các số liệu thống kê thông báo trống. Cảm ơn mọi người!

+0

Chào mừng bạn đến với Stack Overflow. Bạn có lẽ nên bao gồm mã bạn sử dụng để gán vPropertyInfo. Nếu không, bạn không thể chắc chắn kết quả của mình không đơn giản là do bạn có thông tin thuộc tính sai. Ngoài ra, là lớp cơ sở của lớp học của bạn có liên quan, hoặc bạn có được kết quả tương tự từ TObject hoặc TPersistent? [Chỉnh sửa] câu hỏi của bạn để thêm chi tiết. –

+0

Đã chỉnh sửa để hiển thị cách nhận PPropInfo. Lớp được liệt kê ở trên, nó được thừa hưởng từ TInterfacedPersistent, vì vậy tôi có thể làm việc với RTTI trong các thuộc tính đã xuất bản. Cảm ơn đã giúp đỡ. –

+1

Bạn sử dụng phương pháp VIRTUAL làm setter. các biến, phương thức tĩnh và các phương thức ảo có ngữ nghĩa khác nhau. Để kiểm tra giải thích này, hãy xóa "virtual" sau khi setter và kiểm tra xem mã của bạn có bắt đầu hoạt động hay không. Ngoài ra, tôi nghĩ rằng bạn đặt một điểm ngắt và giá trị của 'IntToHex (vPropList [I] ^. SetProc)' - nó nên đã chỉ ra rằng nó là không thể tin được nhỏ là một con trỏ thực sự. –

Trả lời

0

đọc c:\rad studio\9.0\source\rtl\common\System.Rtti.pas

procedure TRttiInstanceProperty.DoSetValue 

Các setter của tài sản có thể

  • một lĩnh vực (variable)
  • một thủ tục tĩnh
  • một thủ tục ảo (trường hợp của bạn)

Và những trường hợp đó làm cho PropInfo^.SetProc có ngữ nghĩa khác nhau về giá trị của nó. Địa chỉ trực tiếp chỉ áp dụng cho các thủ tục tĩnh. Đối với các phương thức ảo, bạn thêm một giá trị VMT và lấy địa chỉ mã từ ô nhớ đó, như được chỉ rõ trong mã mà tôi đã đề cập (nhưng sẽ không trích dẫn vì lý do bản quyền).

Hoặc bạn chỉ có thể sử dụng TRttiProperty.SetValue và để Delphi thực hiện tất cả những điều đó dưới chi tiết mui xe.Xem http://docwiki.embarcadero.com/Libraries/XE2/en/System.Rtti.TRttiProperty.SetValue

EDIT:

  1. mã loại bỏ - nó không làm việc đúng nguyên văn và khởi động chủ đề được cung cấp phiên bản làm việc.
  2. Về và tôi biết tôi nên sử dụng Extended RTTI thay vì classic một - đó là khiếu nại có vấn đề. Extended RTTI được biết là hoạt động chậm hơn đáng kể so với phiên bản cổ điển. Dunno nếu ai đó đã lược tả nó, nhưng tôi nghi ngờ rằng chủ yếu là do mã chậm của TValue. Bạn có thể google và thấy rằng rất nhiều người phàn nàn chậm thực hiện TValue và cung cấp những thay thế với hiệu quả cố định. Tuy nhiên, kể từ khi Extended RTTI chỉ sử dụng cổ phiếu TValue, nó không thể được hưởng lợi từ những triển khai đó và vẫn chậm hơn phiên bản cũ.
+0

Tôi gõ nhầm nó, nó thực sự trong phần được xuất bản.Và mặc dù tôi có thể nắm bắt các thuộc tính (tên, giá trị, và như vậy ...), hàm "MethodName" vẫn còn làm mới một chuỗi rỗng: (... –

+0

http://docwiki.embarcadero.com/Libraries/XE2/en/System.Rtti.TRttiProperty.SetValue tìm kiếm phương pháp bỏ qua? –

+0

Tôi đã thử mẫu cuối cùng của bạn, nhưng tôi có "Vi phạm Truy cập" tại "P: = PPointer (P)^"dòng. –

2

Bạn có thể lấy tên phương pháp này, nếu

a) di chuyển phương pháp để các bố phần (cổ điển RTTI làm việc với phần này chỉ (chính xác hơn - biên soạn với {$ M +} chỉ thị))

b) quyền sử dụng lớp specifier - MyClass.MethodName, vì methodname là chức năng lớp

mã này hoạt động trên D7 và XE3:

MyClass = class(TInterfacedPersistent) 
private 
    FMyProperty: Integer; 
published 
    procedure setMyProperty(Value: Integer); 
    property MyProperty: Integer read FMyProperty write setMyProperty; 
end; 


procedure TForm1.Button1Click(Sender: TObject); 
var 
    ppi: PPropInfo; 
begin 
    ppi := GetPropInfo(MyClass, 'MyProperty'); 
    ShowMessage(MyClass.MethodName(ppi.SetProc)); 
end; 

P.S. Bạn đang sử dụng phiên bản Delphi nào? Điều gì về Extended RTTI (kể từ D2010)?

+0

Cảm ơn bạn rất nhiều vì đã trả lời, tôi ' m sẽ thử cái này Bạn có thể cho thấy một ví dụ về làm thế nào tôi có thể làm điều này với RTTI mở rộng? Không cần những điều cơ bản, chỉ có bản thân mã. Và cảm ơn trước vì điều này. :) –

+0

Xin lỗi, tôi không thấy một khả năng để có được phương pháp setter trong TRttiProperty, nó chỉ có sẵn cho các thuộc tính được lập chỉ mục. Nhưng .. tại sao bạn muốn biết tên phương pháp? – MBo

+0

Tôi đang triển khai một khuôn khổ áp dụng các khái niệm AOP bằng cách sử dụng TVirtualMethodInterceptor, để thực hiện những việc như thông báo cho các quan sát viên khi một poperty đã thay đổi. Vì vậy, điều đó sẽ hữu ích cho tôi để thực hiện một tầng chung chung hơn và decouple những điều. Tuy nhiên, tôi sẽ thử mẹo đầu tiên. Cảm ơn nhiều. –