الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كيف تحفظ و تسترجع كائنات الدوت نت حتى بعد غلق البرنامج

بدأه محمد رضى في 26 أغسطس 2009 · 9 رد · 2,760 مشاهدة · في قسم الدروس والمواضيع المتميزة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم و رحمة الله تعالى و بركاته,,,

لعل من بين اللغات البرمجية المستعملة الآن هي XML المعرفة كـ Extensible Markup Language. لن أخوض في وضع تعريف لهذه اللغة لأن هناك العديد من المواقع و الكتب التي تقدم تعريفات و معلومات كاملة عنها و هذا رابط حيث ستجدون المعلومات التي تحتاجونها في الموضوع XML (Extensible Markup Language). المهم أن تقريبا لا تكاد تجد تقنية من التقنيات الجديدة لا تستعمل لغة XML و ما يهمنا هنا هو أحد استعمالاتها في لغات الدوت نت.

من منا نحن المبرمجين لم يحتج يوما لحفظ كائن من الذاكرة الحية إلى و حدة تخزين؟ الفكرة تبدو سهلة و لكن تطبيقها صعب, أليس كذلك؟ الجواب على هذين السؤالين جانب صغير واحد من الجوانب التي أثبتت XML جدارتها و فعاليتها فيه. لغات الدوت نت تتيح للمبرمج تحويل أي كائن من صيغته الثنائية العادية على الذاكرة الحية إلى صيغة مقروءة بلغة XML. لغة الدوت نت تضع رهن إشارتنا العديد السمات أو attributes لوضع علامة على كل متغير أو كائن داخل الكلاس لتعريف طريقة حفظه من الذاكرة الحية و استرجاعه من ملف على وحدة تخزين. و من بين هذه السمات :

XmlArrayAttribute : تعرف الكائن أو المتغير ليتم حفظه على شكل مصفوفة.

XmlAttributeAttribute : تعرف الكائن أو المتغير على أنه سمة للكائن المعرف بداخله.

XmlElementAttribute : تعرف الكائن أو المتغير على أنه عنصر من العناصر المكونة للكائن المعرف بداخله.

XmlEnumAttribute : تعرف المتغير ليتم حفظه كنوع enum.

XmlIgnoreAttribute : تضع علامة على الكائن أو المتغير ليتم تجاهله في مرحلة الحفظ.

XmlTextAttribute : تعرف الكائن أو المتغير ليتم حفظه كنص XML.

قبل البدء في التطبيق تجدر الإشارة إلى أن الكلاس XmlSerializer هي التي تتكلف بحفظ كائن على شكل ملف XML و السمات التي ذكرنا تساعدها في التعرف على كل كائن أو متغير و تقوم بحفظه بالشكل الذي نريد و الذي حددناه عن طريق السمة XML مباشرة قبل تعريف الكائن أو المتغير. فمثلا الكود التالي يعرف لنا s على أنه متغير من نوع string سيتم حفظه على أنه عنصر من عناصر الكائن الحاوي له.

  <XmlElement()> Public s As String

الآن و بعد أن تعرفنا على السمات المعرفة لعناصر كلاس من متغيرات و كائنات دعونا نطبق بعضها على الكلاس Test حتى تصبح الكائنات المنشئة منها قابلة للحفظ و الإسترجاع بكل سهولة. لعدم الإطالة و التعقيد سنستعمل فقط السمات XmlElementAttribute و XmlArrayAttribute. يمكنكم تجريب باقي السمات لملاحظة الفرق في ملف XML نتيجة عملية الحفظ. لنفترض أنه لدينا في مشروع كلاس معرفة كالتالي :

	  Public Class Test
		  Public string_element As String
		  Public int_element As Integer
		  Public double_element As Integer
		  Public datetime_element As DateTime
		  Public array_elements(3) As String
		  Public ot As New OtherTest()

		  Public Sub InitData()
			  string_element = "string"
			  int_element = 123456789
			  double_element = Math.PI
			  datetime_element = DateTime.Now
			  array_elements(0) = "one"
			  array_elements(1) = "two"
			  array_elements(2) = "tree"
			  array_elements(3) = "four"
		  End Sub
	  End Class

عندنا ثلاثة أنواع من بنية البيانات في الكلاس أعلاه. النوع الأول نوع عادي مم نستعمله في حياتنا اليومية العملية و سنعرف كل واحد منها بالسمة XmlElementAttribute. النوع الثاني هو المصفوفة array_element التي سنعرفها بالسمة XmlArrayAttribute. النوع الثالث هو الكائن ot للكلاس OtherTest الذي سنعرفه كما نعرف بنية البيانات الأساسية بشرط أن الكائنات المعرفة داخله تكون هي الأخرى معرفة بسمات XML. في الأخير ستكون النتيجة كالتالي :

	  Public Class Test
		  <XmlElement()> _
		  Public string_element As String
		  <XmlElement()> _
		  Public int_element As Integer
		  <XmlElement()> _
		  Public double_element As Integer
		  <XmlElement()> _
		  Public datetime_element As DateTime
		  <XmlArray()> _
		  Public array_elements(3) As String
		  <XmlElement()> _
		  Public ot As New OtherTest()

		  Public Sub InitData()
			  string_element = "string"
			  int_element = 123456789
			  double_element = Math.PI
			  datetime_element = DateTime.Now
			  array_elements(0) = "one"
			  array_elements(1) = "two"
			  array_elements(2) = "tree"
			  array_elements(3) = "four"
		  End Sub
	  End Class

الآن يمكننا دراسة الكود الذي سينشئ لنا نسخة XML من الكائن الذي أنشأناه من الكلاس المبينة أعلاه و يسجلها على ملف لنتمكن من استرجاع الكائن متى شئنا. الكود بسيط للغاية و لا يتعدى بضعة أسطر :

		  Dim t As new Test()
		  t.InitData() 
		  Dim strm As Stream = File.Open(fileName, FileMode.Create)
		  Dim ser As New XmlSerializer(t.GetType())
		  ser.Serialize(strm, t)
		  strm.Close()

الجملة الأولى تنشئ لنا الملف الذي بداخله سيقوم الكائن ser المنشأ من الكلاس XmlSerializer, سيقوم بإنشاء نص XML به كل المعلومات الضرورية لاسترجاع الكائن في أي زمان و على أي حاسوب. الجملة الثانية ننشئ الكائن ser و نعرفه على نوع الكائن الذي نريد تحويله إلى نص XML. الجملة الثالثة تقوم بكتابة محتوى الكائن أي نص XML في الملف المفتوح. و ستكون النتيجة على الشكل التالي :

  <?xml version="1.0"?>
  <Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" int_element="123456789">
	<string_element>string</string_element>
	<double_element>3</double_element>
	<datetime_element>2009-08-26T12:07:08.545521+00:00</datetime_element>
	<array_elements>
	  <string>one</string>
	  <string>two</string>
	  <string>tree</string>
	  <string>four</string>
	</array_elements>
	<ot>
	  <name>OtherTest object</name>
	  <now>2009-08-26T12:07:08.3492445+00:00</now>
	</ot>
  </Test>

النتيجة تكون ملف يحتوي على نص XML به كل المعلومات عن الكائن الموجود بالذاكرة الحية. و هذا الملف سهل القراءة يمكن إرساله عبر الشبكات الداخلية و عبر الانترنت بكل سهولة و هنا تظهر فعالية XML. كما يمكن بسهولة تغيير محتوى النص XML حتى نتحكم بمحتوى الكائن المسترجع. و لاسترجاع الكائن من على الملف بوحدة التخزين إلى الذاكرة الحية نقوم بعكس العملية التي هي سهلة و بسيطة بساطة عملية الحفظ.

		  Dim strm As Stream = File.Open(fileName, FileMode.Open)
		  Dim ser As New XmlSerializer(typeObj)
		  Dim obj As Object = ser.Deserialize(strm)
		  strm.Close()

كود استرجاع الكائن شبيه تماما بكود الحفظ إلا أننا في هذه الحالة سنقوم بفتح الملف للقراءة و نقوم بالمناداة على الدالة Deserialize التي ستنشئ لنا كائنا نسخة طبق الأصل من الكائن الذي قمنا بحفظه. بقي أن نحول الكائن obj إلى نوع الكائن الأصلي ألا و هو Test.

نقطة أخيرة, هي أن كل الكائنات و المتغيرات التي نريد أن يتم حفظها مع الكائن الحاوي لها يجب أن تكون معرفة على أنها Public و كذل الأمر بالنسبة للكائن الحاوي و الموديل كذلك.

أتمنى أن يكون هذا الموضوع مفيدا. و أتمنى أن أكون قد أوصلته بالشكل الذي يضمن الفهم الجيد.

في الملف المرفق مع هذا الموضوع مشروع صغير يمكن تتبع تنفيذه جملة جملة عن طريق الضغط على الزر F8 للمزيد من الفهم. الملف فيه كذلك كود الجزء الثاني من هذا الموضوع. يتبع...

تحياتي...

ConsoleApplication2.rar

تم تعديل هذه المشاركة بواسطة محمد رضى في 26 أغسطس 2009 في 16:41

#2

نريد درس كهذا فى قسم السى شارب :lol:

لا إله إلا الله محمد رسول الله

アッラー以外に神はなし。ムハンマドはアッラーの使徒である

#3

السلام عليكم و رحمة الله تعالى و بركاته,,,

في هذا الجزء الثاني و الأخير من هذا الموضوع سنتكلم فيه عن طريقة أخرى لحفظ و استرجاع كائنات الدوت نت. الفرق بينها وبين الطريقة الأولى هو نتيجة عملية الحفظ. فكما الطريقة الأولى تنشئ لنا نص XML مقروء و مفهوم فكما هي هذه الطريقة التي سنرى الآن ستنشئ لنا ملف binary غير مقروء و غير مفهوم و صغير بالنسبة للحجم. الاختيار بين الطريقتين محسوم الآن.

هذه الطريقة لا تحتاج لوضع علامة على كل متغير أو كائن ليتم حفظه. كل ما نحتاجه هو زيادة السطر التالي مباشرة فوق تعريف الكلاس التي نريد حفظ الكائنات المنشئة بها :

<Serializable()> _

مثال :

  <Serializable()>_
  Public Class Test
  …
  End Class

انتهى العمل؟ لا بالطبع, و لكن لم يبق إلا القليل.

لحفظ كائن بهذه الطريقة, نحتاج و كما قمنا بذلك سابقا إلى كائن من نوع Stream تم عن طريقه فتح ملف للإنشاء و الكتابة و بعد ذلك ننشئ كائن من نوع BinaryFormatter الذي سيقوم بعملية الحفظ داخل الملف المفتوح لهذا الغرض ثم ننادي على الدالة Serialize التي تستقبل كائن Stream للملف المفتوح و الكائن المراد حفظه.

		  Dim binfor As New BinaryFormatter()
		  binfor.Serialize(strm, obj)

عملية الاسترجاع تتم تقريبا بنفس العملية. حيث سنحتاج كذلك لكائن Stream للملف المفتوح للقراءة و بعد ذلك ننس... وصلني للتو عبر البريد الإلكتروني تنبيه بجواب الأخ الفاضل محمد نور. صوت التنبيه الحاد قطع حبل أفكاري... لحظة من فظلكم... أين هو حبل أفكاري؟... :blink:

طبعا أخي محمد. سيكون من دواعي سروري :)

عملية الاسترجاع تتم تقريبا بنفس الطريقة. حيث سنحتاج كذلك لكائن Stream للملف المفتوح للقراءة و بعد ذلك ننشئ كائن من نوع BinaryFormatter الذي سيقوم هو نفسه كما هو الحال بالنسبة XmlSerializer بعملية قراءة محتوى الملف و استرجاع الكائن عن طريق إنشاء نسخة طبق الأصل منه و إرجاعها لنا ككائن من نوع Object الذي بعملية تحويل بسيطة نحصل على الكائن الأصلي.

		  Dim binfor As New BinaryFormatter()
		  Dim obj As Object = binfor.Deserialize(strm)

في الملف المرفق مع الجزء الأول من هذا الموضوع ستجدون كود حفظ/استرجاع الكائنات بطريقة XML و Binary. لتجربة طريقة binary يكفي استبدال كود الدالة Main بالكود التالي :

		  Dim t As New Test()
		  t.InitData()
		  SerializeObject2Binary(t, ".\test.bin")
		  t = Nothing
		  t = DeserializeObjectFromBinary(GetType(Test), ".\test.bin")

طريقتان بسيطتان لحفظ كائن دوت نت حتى بعد غلق البرنامج...

طريقتان بسيطتان لتسجيل معلومات عن كائن كان نموذجا, مربعا, ...

طريقتان بسيطتان لتسجيل معلومات عن مستخدم(ـين), لاعب(ـين), ...

...

تحياتي...

تم تعديل هذه المشاركة بواسطة محمد رضى في 26 أغسطس 2009 في 18:56

1
#4

الحمد لله إنك لقيت الحبل وكملت الدرس الجميل ده :D

إن قلت قال الله قال رسولـه همزوك همز المنكر المتعالي
أو قلت قد قال الصحابة والألـى تبعاً لهم بالقول والأعمال
أو قلت قـال الشافعي وأحمد و أبو حنيفة والإمام الغالي
صدوا عن وحي الإله ودينـه واحتالوا على حرام الله بالإحلال
يا أمةً لعبت بدين نبيها كتلاعب الصبيان في الأوحال
حاشا رسول الله يحكم بالهوى تلك إذاً حكومة الضلال

feed.1.gif

#5

السلام عليكم و رحمة الله و بركاته ،،،

كسرتني بحجار لطفك , و شلليط حنانك , كنت بخزن المتغيرات ب XML او ini و لكن بطريقة بدائية , هذه طريقة افضل بكثير , شكرا لك ;)

<EMBED src=http://www.abdelghafar.com/images/banners/bm2.swf width=486 height=60 type=application/x-shockwave-flash EMBED < menu="false" loop="true" quality="high">

#6

ما شاء الله موضوع رائع

بارك الله فيك

#7

بالنسبة لل binary serialization، في الجافا، لا يتم عمل serialization للمتغيرات static، وأيضا المتغيرات transient، فهل هناك أية قيود مشابهة في .NET أم أنه يتم حفط جميع المتغيرات؟؟

مجرد فضول :)

#8

هذه أنواع المتغيرات التي لا يتم عمل serialize لها :

اقتباس
XML Serialization serializes the public fields and properties of a class, or the parameters and return values of methods into an XML stream. XML Serialization does not include methods, indexers, private fields, or read-only properties (except read-only collections).

و كذلك :

اقتباس

Serialization of ArrayList and Generic List

The XmlSerializer cannot serialize or deserialize the following:

*

Arrays of ArrayList

*

Arrays of List<(Of <(T>)>)

Serialization of Enumerations of Unsigned Long

The XmlSerializer cannot be instantiated to serialize an enumeration if the following conditions are true: The enumeration is of type unsigned long (ulong in C#) and the enumeration contains any member with a value larger than 9,223,372,036,854,775,807. For example, the following cannot be serialized.

public enum LargeNumbers: ulong
{
    a = 9223372036854775808
}
// At runtime, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));

Objects marked with the Obsolete Attribute no longer serialized

In the .NET Framework 3.5 the XmlSerializer class no longer serializes objects that are marked as [Obsolete].

المصدر MSDN

#9

بارك الله فيك يا اخ محمد

على ما تقدم لنا من معلومات

#10

شكرااااااااااااا الله يعطيك العافيه وسلامه

مواضيع مشابهة