2012-07-05 16 views
5

डेल्फी 2010 और आरटीटीआई का उपयोग करके, मुझे पता है कि किसी ऑब्जेक्ट के वर्ग प्रकार को कैसे प्राप्त करें और किसी वस्तु के गुणों के मूल्य और प्रकार को कैसे प्राप्त/सेट करें, लेकिन आप कैसे निर्धारित करते हैं कि कौन सी कक्षा विरासत श्रृंखला एक संपत्ति से आया था? मैं मुख्य वर्ग की तुलना में बेस क्लास के गुणों का अलग-अलग उपयोग करना चाहता हूं।डेल्फी आरटीटीआई: संपत्ति की कक्षा

TClassBase = class(TObject) 
published 
    property A: Integer; 
end; 

TClassDescendant = class(TClassBase) 
published 
    property B: Integer; 
end; 

procedure CheckProperties(Obj: TObject); 
var 
    ctx: TRttiContext; 
    objType: TRttiType; 
    Prop: TRttiProperty; 
begin 
    ctx := TRttiContext.Create; 
    objType := ctx.GetType(Obj.ClassInfo); 
    for Prop in objType.GetProperties do begin 
    if Prop.GetClassType is TClassBase then 
     // do something special with base class properties 
    else 
     // standard functionality on all other properties 
    end; 
end; 

समस्या गुण के लिए कोई GetClassType वहाँ है:

इस कोड पर विचार करें। क्लासटाइप केवल उस वर्ग के नाम के बजाय TRttiInstancePropertyEx देता है जिस पर संपत्ति संबंधित है।

+1

आपका प्रश्न थोड़ा उलझन में है। कृपया साफ़ करें। आप वास्तव में क्या ढूंढ रहे हैं? क्या आप यह निर्धारित करने की कोशिश कर रहे हैं कि 'Obj.PropertyName' एक ऑब्जेक्ट लौटाता है जो 'TClassDescendant' उदाहरण बनाम' TClassBase' उदाहरण है? या फिर आप यह निर्धारित करने की कोशिश कर रहे हैं कि 'Obj.PropertyName' को' TClassBase' के रूप में घोषित किया गया है, भले ही किस प्रकार का ऑब्जेक्ट आवृत्ति लागू होता है? आप जिस वस्तु (ओं) की जांच कर रहे हैं, द्वारा 'TClassBase' और' TClassDescendant' का उपयोग कैसे किया जा रहा है? –

+0

मैं जानना चाहता हूं कि "आप कैसे निर्धारित करते हैं कि विरासत श्रृंखला में कौन सी कक्षा से एक संपत्ति आई है" या फिर TClassBase में संपत्ति या TClassDescendant में है। चूंकि मैं कक्षा के गुणों को पार कर रहा हूं, मैं बेस क्लास गुणों को अनदेखा करना चाहता हूं। मेरी विशेष स्थिति में, मैंने TInterfacedObject से एक वर्ग को जन्म दिया है और जब तक उनके पास [अनदेखा] विशेषता नहीं है, तब तक सभी गुणों पर एक फ़ंक्शन निष्पादित कर रहा हूं, लेकिन मैं आसानी से TInterfacedObject से RefCount को अनदेखा करना चाहता हूं। –

+0

यह जांचने के बजाय कि वर्तमान संपत्ति किसी विशिष्ट वर्ग में मौजूद है या नहीं, यह जांचने के लिए और अधिक समझदारी होगी कि ऑब्जेक्ट की गणना की जाने वाली वस्तु इच्छित वर्ग है या नहीं। यह लागू करना और अधिक सटीक होना बहुत आसान होगा। –

उत्तर

5

एक अन्य विकल्प, TRttiProperty की Parent संपत्ति का उपयोग यहाँ से आप वर्ग जो संपत्ति का हिस्सा है करने के लिए उपयोग कर सकते हैं है।

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    Rtti, 
    SysUtils; 

type 
    TClassBase = class(TObject) 
    private 
     FA: Integer; 
    published 
    property A: Integer read FA; 
    end; 

    TClassDescendant = class(TClassBase) 
    private 
     FB: Integer; 
    published 
    property B: Integer read FB; 
    end; 

procedure CheckProperties(Obj: TObject); 
var 
    ctx: TRttiContext; 
    objType: TRttiType; 
    Prop: TRttiProperty; 
begin 
    ctx := TRttiContext.Create; 
    objType := ctx.GetType(Obj.ClassInfo); 
    for Prop in objType.GetProperties do 
    if TRttiInstanceType(Prop.Parent).MetaclassType=TClassBase then 
    Writeln(Format('The property %s is declarated in the TClassBase class',[Prop.Name])) 
    else 
    Writeln(Format('The property %s is not declarated in the TClassBase class',[Prop.Name])) 
end; 


begin 
    try 
    //CheckProperties(TClassBase.Create); 
    CheckProperties(TClassDescendant.Create); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 
+0

बिल्कुल सही! वास्तव में मुझे जो चाहिए था, उसे नहीं पता था कि वहां कैसे जाना है। धन्यवाद। –

2

मैं अगर यह वर्ग है जो एक संपत्ति पेश किया गया था प्राप्त करना संभव है पता नहीं है, लेकिन आप नियमित रूप से RTTI साथ अपनी समस्या को हल कर सकते हैं: गुण में declarated पाने के लिए

begin 
    ... 

    for Prop in objType.GetProperties do begin 
    if Assigned(GetPropInfo(TClassBase, Prop.Name)) then 
     // do something special with base class properties 
    else 
     // standard functionality on all other properties 
    end; 
end; 
+0

मुझे नहीं लगता कि यह वही काम कर रहा है जिसे उपयोगकर्ता ने मांगा था। आप यह देखने के लिए TClassBase क्लास को स्वयं देख रहे हैं कि क्या यह एक दी गई संपत्ति है, लेकिन मुझे लगता है कि उपयोगकर्ता यह जांचने के लिए कह रहा है कि किसी अन्य वर्ग की संपत्ति TClassBase उदाहरण या इसके बजाय एक वंशज उदाहरण है या नहीं। –

+0

@Remy - प्रश्न में काल्पनिक कोड जांचता है कि 'TClassBase' में एक अनुमानित संपत्ति पहले ही पेश की जा चुकी है या नहीं। कम से कम यही मुझे समझ में आया। यद्यपि आप बहुत अच्छे हो सकते हैं .. –

+1

मैंने अभी कोशिश की है और इससे समस्या हल हो जाती है। धन्यवाद! –

2

आप GetDeclaredProperties विधि का उपयोग कर सकते हैं वर्तमान वर्ग और फिर GetProperties विधि द्वारा लौटाए गए मानों के विरुद्ध तुलना करें।

इस नमूना को आजमाएं।

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    Rtti, 
    SysUtils; 

type 
    TClassBase = class(TObject) 
    private 
     FA: Integer; 
    published 
    property A: Integer read FA; 
    end; 

    TClassDescendant = class(TClassBase) 
    private 
     FB: Integer; 
    published 
    property B: Integer read FB; 
    end; 

procedure CheckProperties(Obj: TObject); 

    function ExistProp(const PropName:string; List:TArray<TRttiProperty>) : Boolean; 
    var 
    Prop: TRttiProperty; 
    begin 
    result:=False; 
    for Prop in List do 
    if SameText(PropName, Prop.Name) then 
    begin 
     Result:=True; 
     break; 
    end; 
    end; 

var 
    ctx: TRttiContext; 
    objType: TRttiType; 
    Prop: TRttiProperty; 
    CurrentClassProps : TArray<TRttiProperty>; 
begin 
    ctx := TRttiContext.Create; 
    objType := ctx.GetType(Obj.ClassInfo); 
    CurrentClassProps:=objType.GetDeclaredProperties; 
    for Prop in objType.GetProperties do 
    if ExistProp(Prop.Name, CurrentClassProps) then 
    Writeln(Format('The property %s is declarated in the current %s class',[Prop.Name, obj.ClassName])) 
    else 
    Writeln(Format('The property %s is declarated in the base class',[Prop.Name])) 
end; 



begin 
    try 
    //CheckProperties(TClassBase.Create); 
    CheckProperties(TClassDescendant.Create); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 
+0

हां, मैं देख सकता हूं कि यह कैसे काम करेगा - यह लंबा रास्ता है। –

संबंधित मुद्दे