لماذا لا يمكن استخدام السمة "غير المعدلة" على مستوى الفصل؟ كيف تمنع تسلسل الطبقة؟
-
20-09-2019 - |
سؤال
لدي كائن بيانات يتم تعديله عميقًا باستخدام تسلسل ثنائي. يدعم كائن البيانات هذا الملكية الأحداث التي تم تغييرها ، على سبيل المثال ، 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]
سمات في المقام الأول!)