2009-03-06 5 views
12

मेरे पास लगभग एक सौ इकाई वर्ग हैं जो इस तरह दिख रहे हैं:एक [Serializable] INotifyPropertyChanged कार्यान्वयन से nonserializable पर्यवेक्षकों को कैसे बाहर निकालें?

[Serializable] 
public class SampleEntity : INotifyPropertyChanged 
{ 
    private string name; 
    public string Name 
    { 
     get { return this.name; } 
     set { this.name = value; FirePropertyChanged("Name"); } 
    } 

    [field:NonSerialized] 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void FirePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, 
       new PropertyChangedEventArgs(propertyName)); 
    } 
} 

PropertyChanged पर [field:NonSerialized] विशेषता को नोटिस करें। यह आवश्यक है क्योंकि कुछ पर्यवेक्षकों (मेरे मामले में - संस्करण के लिए इकाइयों को प्रदर्शित करने वाला ग्रिड) क्रमिक नहीं हो सकता है, और इकाई को धारावाहिक होना चाहिए, क्योंकि यह प्रदान किया जाता है - रिमोटिंग के माध्यम से - एक सेपरेटर मशीन पर चल रहे किसी एप्लिकेशन द्वारा ।

यह समाधान मामूली मामलों के लिए ठीक काम करता है। हालांकि, यह संभव है कि कुछ पर्यवेक्षक [Serializable] हैं, और संरक्षित होने की आवश्यकता होगी। मुझे इसे कैसे नियंत्रित करना चाहिए?

समाधान मैं विचार कर रहा हूं:

  • पूर्ण ISerializable - कस्टम क्रमिकरण के लिए बहुत सारे कोड लिखने की आवश्यकता है, मैं [OnSerializing]
  • का उपयोग [OnSerializing] और [OnDeserializing] विशेषताओं को PropertyChanged मैन्युअल रूप से क्रमबद्ध करने के लिए नहीं करना चाहूंगा - लेकिन वे सहायक विधि केवल SerializationContext प्रदान करते हैं, जो AFAIK क्रमबद्धता डेटा संग्रहीत नहीं करता है (SerializationInfo वह करता है)

उत्तर

12

आप righ कर रहे हैं टी कि पहला विकल्प अधिक काम है। हालांकि यह आपको संभावित रूप से एक अधिक कुशल कार्यान्वयन दे सकता है, यह आपकी संस्थाओं को बहुत जटिल करेगा। इस बात पर विचार करें कि यदि आपके पास Entity कक्षा है जो ISerializable लागू करता है, सभी उप-वर्गों को क्रमशः क्रमिकरण लागू करना होगा!

काम करने के लिए दूसरा विकल्प प्राप्त करने के लिए चाल, के रूप में गैर serializable घटना अंकन जारी रखने के लिए, लेकिन वह serializable है एक दूसरे क्षेत्र के लिए और आप उचित क्रमबद्धता हुक के दौरान अपने आप को पॉप्युलेट है। यहां एक नमूना मैं बस आप को दिखाने के लिए कैसे लिखा है:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var entity = new Entity(); 
      entity.PropertyChanged += new SerializableHandler().PropertyChanged; 
      entity.PropertyChanged += new NonSerializableHandler().PropertyChanged; 

      Console.WriteLine("Before serialization:"); 
      entity.Name = "Someone"; 

      using (var memoryStream = new MemoryStream()) 
      { 
       var binaryFormatter = new BinaryFormatter(); 
       binaryFormatter.Serialize(memoryStream, entity); 
       memoryStream.Position = 0; 
       entity = binaryFormatter.Deserialize(memoryStream) as Entity; 
      } 

      Console.WriteLine(); 
      Console.WriteLine("After serialization:"); 
      entity.Name = "Kent"; 

      Console.WriteLine(); 
      Console.WriteLine("Done - press any key"); 
      Console.ReadKey(); 
     } 

     [Serializable] 
     private class SerializableHandler 
     { 
      public void PropertyChanged(object sender, PropertyChangedEventArgs e) 
      { 
       Console.WriteLine(" Serializable handler called"); 
      } 
     } 

     private class NonSerializableHandler 
     { 
      public void PropertyChanged(object sender, PropertyChangedEventArgs e) 
      { 
       Console.WriteLine(" Non-serializable handler called"); 
      } 
     } 
    } 

    [Serializable] 
    public class Entity : INotifyPropertyChanged 
    { 
     private string _name; 
     private readonly List<Delegate> _serializableDelegates; 

     public Entity() 
     { 
      _serializableDelegates = new List<Delegate>(); 
     } 

     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       if (_name != value) 
       { 
        _name = value; 
        OnPropertyChanged("Name"); 
       } 
      } 
     } 

     [field:NonSerialized] 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
     { 
      var handler = PropertyChanged; 

      if (handler != null) 
      { 
       handler(this, e); 
      } 
     } 

     protected void OnPropertyChanged(string propertyName) 
     { 
      OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
     } 

     [OnSerializing] 
     public void OnSerializing(StreamingContext context) 
     { 
      _serializableDelegates.Clear(); 
      var handler = PropertyChanged; 

      if (handler != null) 
      { 
       foreach (var invocation in handler.GetInvocationList()) 
       { 
        if (invocation.Target.GetType().IsSerializable) 
        { 
         _serializableDelegates.Add(invocation); 
        } 
       } 
      } 
     } 

     [OnDeserialized] 
     public void OnDeserialized(StreamingContext context) 
     { 
      foreach (var invocation in _serializableDelegates) 
      { 
       PropertyChanged += (PropertyChangedEventHandler)invocation; 
      } 
     } 
    } 
} 
+0

आमंत्रण। लक्ष्य शून्य (अज्ञात प्रतिनिधियों के लिए) हो सकता है, इस – skolima

+0

की जांच करना सुनिश्चित करें उन घटनाओं का XmlSerializer पर कोई प्रभाव नहीं पड़ता है (ठीक है, मुझे केवल काम करने के लिए रिमोटिंग की आवश्यकता है)। – skolima

+0

OnSerializing और OnDeserialized निजी होना चाहिए, उन्हें बेनकाब करने की कोई आवश्यकता नहीं है। – skolima

1

रिच एल साथ सहमत [क्षेत्र: NonSerialized] एक समस्या एक संपत्ति के साथ एक वस्तु serializing के साथ हल करती अधिसूचना यकीन है कि सोने की में बनाया बदल स्निपेट। । धन्यवाद

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