لماذا لا يمكن استخدام السمة "غير المعدلة" على مستوى الفصل؟ كيف تمنع تسلسل الطبقة؟

StackOverflow https://stackoverflow.com/questions/2467376

سؤال

لدي كائن بيانات يتم تعديله عميقًا باستخدام تسلسل ثنائي. يدعم كائن البيانات هذا الملكية الأحداث التي تم تغييرها ، على سبيل المثال ، pricechanged.

دعنا نقول أنني أرفقت معالجًا للمعالج. عندما يحاول الشفرة تسلسلها ، فإنه يلقي استثناءً من أن المعالج غير محدد على أنه قابل للتسلسل.

بدائلي:

  • لا يمكنني إزالة جميع المعالجات بسهولة من الحدث قبل التسلسل
  • لا أريد وضع علامة على المعالج على أنه قابل للتسلسل لأنني يجب أن أميز جميع تبعيات المعالجات بشكل متكرر.
  • لا أرغب في وضع علامة على الأساس على أنها غير محددة - هناك عشرات من الأحداث التي يمكن أن يكون لها معالجات. تحرير: سبب آخر لا يمكنني القيام بذلك هو أن فئات البيانات (وبالتالي الأحداث) يتم إنشاؤها وليس لدي تحكم مباشر في رمز التوليد. من الناحية المثالية ، فإن رمز التوليد سيضع علامة على جميع الأحداث على أنها غير محددة.
  • من الناحية المثالية ، أود .NET أن أتوقف عن النزول في الرسم البياني للكائن في تلك المرحلة وجعل ذلك "ورقة". فلماذا لا تسمح .NET لفئة كاملة لتمييزها على أنها غير محددة؟

--

لقد عملت أخيرًا حول هذه المشكلة من خلال جعل المعالج ينفذ قابلاً للتطبيق وعدم القيام بأي شيء في طريقة مُنشئ/ getDataObject التسلسلية. ولكن ، لا يزال المعالج متسلسلًا ، فقط مع كل تبعياته التي تم تعيينها على Null - لذلك كان عليّ أن أفسر ذلك أيضًا.

هل هناك طريقة أفضل لمنع تسلسل فئة بأكملها؟ وهذا هو ، واحد لا يتطلب حساب التبعيات الفارغة؟

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

المحلول

على الرغم من أنني أميل إلى الاختلاف مع النهج (أود ببساطة وضع علامة على الأحداث على أنها غير محددة ، بغض النظر عن عددهم) ، ربما يمكنك القيام بذلك باستخدام بدلات التسلسل.

والفكرة هي أنك تقوم بإنشاء كائن يقوم بتنفيذ iserializationsurgate وتفعل ما تفعله بالفعل - لا شيء في أساليب getObjectData و SetObjectData. الفرق هو أنك ستقوم بتخصيص تسلسل المندوب ، وليس الفئة التي تحتوي عليه.

شيء مثل:

class DelegateSerializationSurrogate : ISerializationSurrogate {
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
    }
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
        return null;
    }
}

ثم تقوم بتسجيل هذا مع formatter باستخدام الإجراءات الموضح في هذا العمود MSDN. ثم كلما واجهت Formatter مندوبًا ، فإنها تستخدم البديل بدلاً من التسلسل للمندوب مباشرة.

نصائح أخرى

... هناك عشرات الأحداث ...

شخصياً ، ثم سأضيف فقط العلامات غير المخصصة ، والتي يتم القيام بها بسهولة بالنسبة للأحداث الشبيهة بالميدان عبر:

[field: NonSerialized]
public event SomeEventType SomeEventName;

(لا تحتاج إلى إضافة مندوب دعم يدوي)

ما هي متطلبات التسلسل الخاصة بك بالضبط؟ BinaryFormatter هو من نواح كثيرة أقل ودية من المسلسلات. الآثار المترتبة على الأحداث قبيحة بعض الشيء ، وهي هشة للغاية إذا تم تخزينها (IMO إنها مناسبة حقًا للنقل ، وليس للتخزين).

لكن؛ هناك الكثير من البدائل الجيدة التي من شأنها أن تدعم سيناريوهات "الاستنساخ العميق" الأكثر شيوعًا:

  • XmlSerializer (ولكن يقتصر على الأعضاء العامين)
  • DataContractSerializer / NetDataContractSerializer
  • protobuf-net (والتي تشمل Serializer.DeepClone لهذا الغرض)

(لاحظ أنه في معظم هذا الدعم التسلسلي سيتطلب سمات إضافية ، لذلك لا يختلف كثيرًا عن إضافة [NonSerialized] سمات في المقام الأول!)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top