سؤال

لا بد لي من العمل تطبيقًا قديمًا يستخدم BinaryFormatter لتسلسل بيانات التطبيق في Filestream (على سبيل المثال في ملف يسمى "data.oldformat") دون أي تحسين ، تم تمييز الفئة الرئيسية مع السمة

<serializable()>public MainClass
....... 
end class

ورمز التسلسل

dim b as new binaryformatter
b.serialize(mystream,mymainclass)

في محاولة لتحسين عملية التسلسل/إزالة التسلسل ، جعلت الفصل ببساطة ينفذ الواجهة القابلة للتطبيق وكتبت بعض إجراءات التسلسل الأمثل

<serializable()>public MainClass
       implements ISerializable
....... 
end class

يعمل التحسين بشكل جيد حقًا ، لكن يجب أن أجد طريقة لإعادة توزيع البيانات داخل الملفات القديمة للتوافق المتخلف.

كيف أقوم بذلك؟؟

بيرلويجي

هل كانت مفيدة؟

المحلول

Stmax لديه إجابة ممتازة ، ومع ذلك أود تنفيذه مثل هذا ، والذي يستخدم SerializationEntry.GetEnumerator() بدلاً من try/catch. بهذه الطريقة أكثر نظافة وأسرع بكثير.

public MainClass(SerializationInfo info, StreamingContext context) {
    int version = 0;
    foreach (SerializationEntry s in info)
    {
        if (s.Name == "version") 
        {
            version = (int)s.Value;
            break;
        }
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

أفضل إصدار LINQ باستخدام .firstordefault () ، لكن SerializationInfo لا ينفذ ienumerable - في وجهه ، بغرابة بما فيه الكفاية ، حتى أنه لا ينفذ الواجهة القديمة.

نصائح أخرى

نظرًا لأنك قمت بالفعل بتنفيذ واجهة Iserializable ، فمن المحتمل أيضًا أن تضيف بالفعل المُنشئ المطلوب:

public MainClass(SerializationInfo info, StreamingContext context) {}

يمكنك استخدام كائن Info-Object الذي تم تمريره إلى المُنشئ لاسترداد البيانات من الملف المسلسل. بشكل افتراضي (أي عند عدم تنفيذ عدم وجود غير قابل للتطبيق) ، يتم استخدام أسماء الحقول كمعرفات أثناء التسلسل. لذلك إذا كان لدى فصلك القديم حقل "int x" ، فيمكنك إلغاء تمييز هذا باستخدام:

this.x = info.GetInt32("x");

بالنسبة للإصدارات الأحدث ، عادةً ما أضيف إدخال "إصدار" أثناء التسلسل ، مثل هذا:

public void GetObjectData(SerializationInfo info, StreamingContext context) {
  info.AddValue("version", 1);
  info.AddValue("othervalues", ...);
}

أثناء التخلص من ذلك ، يمكنك التحقق من إدخال الإصدار هذا وتهتز وفقًا لذلك:

public MainClass(SerializationInfo info, StreamingContext context) {
    int version;
    try {
       version = info.GetInt32("version");
    }
    catch {
       version = 0;
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

لم أقم بتجميع هذا الرمز ، فقد يحتوي على أخطاء مطبعية.

امل ان يساعد.

فقط جرب نفس الشيء الذي كنت تفعله حتى الآن

BinaryFormatter b = new BinaryFormatter();
MainClass a = b.DeSerialize(mystream) as MainClass;

لم يغير تطبيق iserializable فصلك الأصلي ، لقد أضفت للتو بعض الطرق

عند تسلسل الكائنات ، قم بإضافة حقل إصدار إضافي (يجب ألا يضيف هذا الكثير من النفقات العامة). ثم في طريقة getObjectData الخاصة بك ، حاول استرداد حقل الإصدار أولاً وبناءً على ما إذا كان هذا موجودًا أم لا (عن طريق اصطياد SerializationException) ، قم بتسليم الطريق القديم أو الطريقة الجديدة. سيكون للطريقة القديمة تسلسل جميع البيانات ، لذا يجب أن تكون قادرًا على الاتصال ... لجميع الحقول.

يجب أن يعمل الرمز السابق الخاص بك. هل تحصل على استثناء؟ حاول استخدام مُنشئ جديد:

 Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top