2011-01-18 17 views
5

मैं डेल्फी सहायता फ़ाइल में घटक टॉस्ट्रिंग अनुभाग में उदाहरण का उपयोग करके किसी ऑब्जेक्ट (टीकंपोनेंट वंश) को क्रमबद्ध और deserializing कर रहा हूँ। ऐसा इसलिए है कि मैं ऑब्जेक्ट को डेटाबेस में VARCHAR फ़ील्ड में संग्रहीत कर सकता हूं।क्या मैं एक कन्स्ट्रक्टर बना सकता हूं जो मेरी ऑब्जेक्ट के एक स्ट्रिंग संस्करण को deserializes?

जब मुझे डेटाबेस में संग्रहीत स्ट्रिंग से मेरी कक्षा का एक नया उदाहरण तत्काल करने की आवश्यकता है, तो क्या मैं CreateFromString(AOwner: TComponent; AData: String) फ़ॉर्म के निर्माता का उपयोग कर ऐसा कर सकता हूं? या क्या मुझे एक गैर-वर्ग विधि का उपयोग करना है जो मेरे घटक वर्ग का उदाहरण देता है?

यदि मैं कन्स्ट्रक्टर संस्करण का उपयोग कर सकता हूं, तो मैं कन्स्ट्रक्टर द्वारा बनाए गए "स्वयं" को रीड कॉम्पोनेंट के वापसी मूल्य को कैसे "मैप" कर सकता हूं?

यहाँ मदद फ़ाइल से अक्रमांकन उदाहरण है:

function StringToComponentProc(Value: string): TComponent; 
var 
    StrStream:TStringStream; 
    BinStream: TMemoryStream; 
begin 
    StrStream := TStringStream.Create(Value); 
    try 
    BinStream := TMemoryStream.Create; 
    try 
     ObjectTextToBinary(StrStream, BinStream); 
     BinStream.Seek(0, soFromBeginning); 
     Result:= BinStream.ReadComponent(nil); 
    finally 
     BinStream.Free; 
    end; 
    finally 
    StrStream.Free; 
    end; 
end; 

उत्तर

6

सामान्य रूप से, हाँ, आप एक कन्स्ट्रक्टर को एक स्ट्रिंग को deserialize कर सकते हैं और उस जानकारी का उपयोग नए उदाहरण को शुरू करने के लिए कर सकते हैं। इसका एक छोटा उदाहरण एक वर्ग होगा जिसमें एक Integer फ़ील्ड होगा। कन्स्ट्रक्टर को एक स्ट्रिंग पास करें और कन्स्ट्रक्टर StrToInt पर कॉल करें और परिणाम के साथ फ़ील्ड को प्रारंभ करें।

लेकिन यदि आपके पास एकमात्र फ़ंक्शन है जो deserialization के लिए है, वह भी उदाहरण बनाता है, तो आप इसे कन्स्ट्रक्टर से उपयोग नहीं कर सकते हैं, तो जब आप केवल एक चाहते थे तो आप दो उदाहरणों के साथ समाप्त हो जाएंगे। एक कन्स्ट्रक्टर के कहने का कोई तरीका नहीं है, "कभी भी ध्यान न रखें; सब कुछ के बाद एक उदाहरण नहीं बनाओ। मुझे पहले से कहीं और मिला है।"

हालांकि, यह वह स्थिति नहीं है जिसमें आप हैं।जैसा कि आपको पता होना चाहिए, TStream.ReadComponent आपको अपना उदाहरण बनाने की अनुमति देता है। यह केवल कक्षा को तुरंत चालू करता है यदि आपने इसे पहले से ही उपयोग करने के लिए एक उदाहरण नहीं दिया है। आप इस तरह अपने निर्माता लिखने के लिए सक्षम होना चाहिए:

constructor TLarryComponent.CreateFromString(const AData: string); 
var 
    StrStream, BinStream: TStream; 
begin 
    Create(nil); 
    StrStream := TStringStream.Create(AData); 
    try 
    BinStream := TMemoryStream.Create; 
    try 
     ObjectTextToBinary(StrStream, BinStream); 
     BinStream.Position := 0; 
     BinStream.ReadComponent(Self); 
    finally 
     BinStream.Free; 
    end; 
    finally 
    StrStream.Free; 
    end; 
end; 

वहाँ हम, वर्तमान वस्तु, Self द्वारा नामित गुजर रहे ReadComponent करने के लिए। धारा धारा में संग्रहीत कक्षा के नाम को अनदेखा कर देगी और मान लीजिए कि वर्तमान वस्तु सही वर्ग का है।

+2

क्या यह संभव है कि आपके कार्यान्वयन में एक छोटी सी बग है? मुझे लगता है कि यह 'बनाना (शून्य)' होना चाहिए; विरासत में नहीं मिला (शून्य); '। "विरासत" के साथ आप TLarryComponent द्वारा पेश किए गए किसी भी फ़ील्ड स्टोरेज और गुणों को याद करते हैं। –

+1

आप सही हैं। मैं सोच रहा था कि 'रीड कॉम्पोनेंट' इसका ख्याल रखेगा, लेकिन मुझे एहसास हुआ कि अब ऐसा कोई रास्ता नहीं है। –

+0

अब पूरी तरह से काम कर रहा है और मेरी समस्या का एक सुंदर समाधान प्रदान कर रहा है। –

3

उपयोग एक स्थिर class function बजाय constructor एक की:

type 
    TYourClass = class(TComponent) 
    public 
    class function CreateFromString(AOwner: TComponent; AData: String): TYourClass; static; 
    end; 

implementation 

class function TYourClass.CreateFromString(AOwner: TComponent; AData: String): TYourClass; 
begin 
    Result := (StringToComponentProc(AData) as TYourClass); 
    if AOwner <> nil then 
    AOwner.InsertComponent(Result); 
end; 

AOwner भाग के बाद से TStream.ReadComponent है एक समस्या है, हालांकि हो सकता है, मालिक के लिए कोई पैरामीटर नहीं।

एक और इतना है कि समस्या के बारे में सवाल यह है:

How can I specify the Owner of component read from a Delphi TStream?

संपादित करें: मैं कोड नमूना नवीनीकृत किया है मालिक भी शामिल करने के लिए।

ध्यान दें कि मालिक की घटक सूची में डालने के लिए डालने वाले घटक के लिए एक अद्वितीय या खाली Name की आवश्यकता होती है।

+0

दरअसल, मालिक समस्या कोई समस्या नहीं है। मैं इसे स्वचालित स्ट्रीमिंग क्षमताओं तक पहुंच प्राप्त करने के लिए केवल एक टीकंपोनेंट वंशज बना रहा हूं। वास्तव में वस्तु का कोई दृश्य प्रतिनिधित्व नहीं है, मैं इसे डिजाइन समय पर उपयोग नहीं करूँगा, और मैं कोड में अपने जीवनकाल का प्रबंधन करूँगा। तो मैं मालिक को छोड़ सकता हूं। –

3

आप इसे class (स्थिर) विधि से कर सकते हैं, लेकिन constructor के माध्यम से ऐसा कर सकते हैं।
डेल्फ़िस के रचनाकारों को केवल बनाए गए उदाहरण पर कंपाइलर आंतरिक द्वारा बुलाया जाता है, जो पहले ही आंशिक रूप से प्रारंभ किया गया है (यह वांछित वर्ग और उदाहरण/फ़ील्ड स्टोरेज शून्य-आउट है)।

यदि आप TStream.ReadComponent का स्रोत देखते हैं, तो आप पाएंगे कि घटकों की असली कक्षा पहले स्रोत स्ट्रीम से पढ़ी जाती है, फिर एक खाली उदाहरण बनाया जाता है और स्ट्रीम से आरटीटीआई द्वारा भरा जाता है और परिणाम के रूप में लौटाया जाता है। जिसका अर्थ है:

TStream.ReadComponent का उपयोग करने के लिए, आपको RegisterClass के माध्यम से अपनी कक्षा को डेल्फ़िस स्ट्रीमिंग सिस्टम में पंजीकृत करने की आवश्यकता होगी।

+0

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

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

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