2012-04-17 12 views
11

में सभी गुणों को लूप कैसे करें मेरे पास मेरे डेल्फी ऐप में एक कक्षा है जहां मैं सभी स्ट्रिंग गुणों को रीसेट करने का एक आसान और गतिशील तरीका चाहता हूं और सभी बूलियन गुणों को गलत तक जहां तक ​​मैं कर सकता हूं वेब पर देखें किसी प्रकार का लूप बनाना संभव है, लेकिन यह कैसे करना मेरे लिए स्पष्ट नहीं है।कक्षा

+4

आप किस डेल्फी संस्करण का उपयोग कर रहे हैं? – zz1433

+0

ठीक है कि मैं भूल गया - मैं डेल्फी एक्सई – OZ8HP

उत्तर

10

के साथ चिह्नित हैं कृपया ध्यान दें, निम्नलिखित कोड प्रकाशित संपत्तियों के लिए ही काम करता है एक वर्ग का! साथ ही, नीचे दिए गए फ़ंक्शन को पारित कक्षा का उदाहरण कम से कम प्रकाशित अनुभाग परिभाषित होना चाहिए!

पुरानी शैली आरटीटीआई का उपयोग करके प्रकाशित स्ट्रिंग प्रॉपर्टी वैल्यू को खाली स्ट्रिंग और बूलियन मानों को गलत तरीके से सेट करने का तरीका बताया गया है।

यदि आपके पास डेल्फी 200 से अधिक डेल्फी है तो आपको tkustring प्रकार गुम हो सकता है। यदि हां, तो बस
यह निम्न कोड से हटा दें:

uses 
    TypInfo; 

procedure ResetPropertyValues(const AObject: TObject); 
var 
    PropIndex: Integer; 
    PropCount: Integer; 
    PropList: PPropList; 
    PropInfo: PPropInfo; 
const 
    TypeKinds: TTypeKinds = [tkEnumeration, tkString, tkLString, tkWString, 
    tkUString]; 
begin 
    PropCount := GetPropList(AObject.ClassInfo, TypeKinds, nil); 
    GetMem(PropList, PropCount * SizeOf(PPropInfo)); 
    try 
    GetPropList(AObject.ClassInfo, TypeKinds, PropList); 
    for PropIndex := 0 to PropCount - 1 do 
    begin 
     PropInfo := PropList^[PropIndex]; 
     if Assigned(PropInfo^.SetProc) then 
     case PropInfo^.PropType^.Kind of 
     tkString, tkLString, tkUString, tkWString: 
      SetStrProp(AObject, PropInfo, ''); 
     tkEnumeration: 
      if GetTypeData(PropInfo^.PropType^)^.BaseType^ = TypeInfo(Boolean) then 
      SetOrdProp(AObject, PropInfo, 0); 
     end; 
    end; 
    finally 
    FreeMem(PropList); 
    end; 
end; 

यहाँ एक सरल परीक्षण कोड (ध्यान दें गुण प्रकाशित किया जाना चाहिए है, अगर वहाँ कक्षा में कोई प्रकाशित गुण हैं, कम से कम खाली प्रकाशित अनुभाग होना चाहिए वहां):

type 
    TSampleClass = class(TObject) 
    private 
    FStringProp: string; 
    FBooleanProp: Boolean; 
    published 
    property StringProp: string read FStringProp write FStringProp; 
    property BooleanProp: Boolean read FBooleanProp write FBooleanProp; 
    end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    SampleClass: TSampleClass; 
begin 
    SampleClass := TSampleClass.Create; 
    try 
    SampleClass.StringProp := 'This must be cleared'; 
    SampleClass.BooleanProp := True; 
    ResetPropertyValues(SampleClass); 
    ShowMessage('StringProp = ' + SampleClass.StringProp + sLineBreak + 
     'BooleanProp = ' + BoolToStr(SampleClass.BooleanProp)); 
    finally 
    SampleClass.Free; 
    end; 
end; 
+1

वापस आने में देरी के लिए खेद है - अन्य परियोजनाओं के साथ व्यस्त रहा :-) – OZ8HP

+0

@ डेविड, धन्यवाद! मैं अपने ['प्रारंभिक संशोधन '] में ऐसा कर रहा हूं (http://stackoverflow.com/revisions/10189686/1)। मुझे नहीं पता कि मैंने इसे इस तरह क्यों तोड़ दिया ... – TLama

15

यदि आप डेल्फी 2010 (और उच्चतर) उपयोगकर्ता हैं तो एक नई आरटीटीआई इकाई (rtti.pas) है। आप इसे अपनी कक्षा और उसके गुणों (डिफ़ॉल्ट रूप से सार्वजनिक गुणों के बारे में रनटाइम जानकारी प्राप्त करने के लिए उपयोग कर सकते हैं, लेकिन आप सुरक्षित और निजी फ़ील्ड जानकारी शामिल करने के लिए {$RTTI} कंपाइलर निर्देश का उपयोग कर सकते हैं)। उदाहरण के लिए हमारे पास 3 सार्वजनिक फ़ील्ड (1 बूलियन और 2 स्ट्रिंग फ़ील्ड्स (उनमें से एक पढ़ा गया है) के साथ अगला टेस्ट क्लास है।

TTest = class(TObject) 
     strict private 
     FString1 : string; 
     FString2 : string; 
     FBool : boolean; 
     public 
     constructor Create(); 
     procedure PrintValues(); 

     property String1 : string read FString1 write FString1; 
     property String2 : string read FString2; 
     property BoolProp : boolean read FBool write FBool; 
    end; 

constructor TTest.Create(); 
begin 
    FBool := true; 
    FString1 := 'test1'; 
    FString2 := 'test2'; 
end; 

procedure TTest.PrintValues(); 
begin 
    writeln('string1 : ', FString1); 
    writeln('string2 : ', FString2); 
    writeln('bool: ', BoolToStr(FBool, true)); 
end; 

वस्तु के सभी गुण की गणना और सेट यह डिफ़ॉल्ट मान आप नीचे दिए गए कोड की तरह कुछ का उपयोग कर सकते करने के लिए। सबसे पहले आपको TRttiContext संरचना में प्रवेश करना होगा (यह स्वीकार्य नहीं है, क्योंकि यह एक रिकॉर्ड है)। फिर आपको अपने ओबेजेक्ट के बारे में आरटीआई जानकारी मिलनी चाहिए, उसके बाद आप अपनी गुणों को लूप कर सकते हैं और इसे फ़िल्टर कर सकते हैं (केवल पढ़ने के गुणों को छोड़ दें और बुलियन और हलचल के अलावा)। को ध्यान में रखें तार के कुछ प्रकार देखते हैं कि: tkUString, tkString और दूसरों परीक्षण करने के लिए

TObjectReset = record 
     strict private 
     public 
     class procedure ResetObject(obj : TObject); static; 
    end; 

{ TObjectReset } 

class procedure TObjectReset.ResetObject(obj: TObject); 
var ctx : TRttiContext; 
    rt : TRttiType; 
    prop : TRttiProperty; 
    value : TValue; 
begin 
    ctx := TRttiContext.Create(); 
    try 
     rt := ctx.GetType(obj.ClassType); 

     for prop in rt.GetProperties() do begin 
      if not prop.IsWritable then continue; 

      case prop.PropertyType.TypeKind of 
       tkEnumeration : value := false; 
       tkUString :  value := ''; 
       else continue; 
      end; 
      prop.SetValue(obj, value); 
     end; 
    finally 
     ctx.Free(); 
    end; 
end; 

सरल कोड (typinfo.pas में TTypeKind पर एक नज़र डालें):

var t : TTest; 
begin 
    t := TTest.Create(); 
    try 
     t.PrintValues(); 
     writeln('reset values'#13#10); 
     TObjectReset.ResetObject(t); 
     t.PrintValues(); 
    finally 
     readln; 
     t.Free(); 
    end; 
end. 

और परिणाम

है
string1 : test1 
string2 : test2 
bool: True 
reset values 

string1 : 
string2 : test2 
bool: False 

पर भी एक नज़र डालें, आईएमओ गुणों को चिह्नित करना अच्छा विचार है (जिसकी आपको आवश्यकता है कुछ विशेषता के साथ पुनर्स्थापित करने के लिए), और जैसे डिफ़ॉल्ट मान के साथ हो सकता है:

[ResetTo('my initial value')] 
property MyValue : string read FValue write FValue; 

तो आप फ़िल्टर कर सकते हैं केवल गुण है जो ResetToAttribute

+0

का उपयोग कर रहा हूं निश्चित रूप से मेरे पास पर काम करने के लिए बहुत सारी जानकारी है, मुझे लगता है कि टेरन का समाधान वह होगा जिसका मैं प्रयोग करूंगा। लेकिन मैं वापस आऊंगा। – OZ8HP

+0

मैं उत्तर को फिर से लिखता हूं क्योंकि मैंने आपके प्रश्न को गलत तरीके से पढ़ा है (सोच रहा है कि आपको घटकों के लिए इसकी आवश्यकता है)। हालांकि प्रकाशित होने के अलावा अन्य गुणों के साथ अपने स्वयं के वर्गों के लिए पुरानी शैली आरटीटीआई अनुपयोगी है। तो निश्चित रूप से इस तरह का पालन करें ;-) – TLama