2009-03-06 10 views
12

Neredeyse yüz varlık sınıflarının böyle bakıyor vardır: PropertyChanged üzerine[Serializable] INotifyPropertyChanged uygulayıcısından düzenlenemeyen gözlemciler nasıl hariç tutulur?

[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)); 
    } 
} 

Bildirimi [field:NonSerialized] niteliği. Bazı gözlemciler (benim durumumda - baskı için tüzel kişilikler gösteren bir ızgara) seri hale getirilemez ve varlık ayırıcı bir makinada çalışan bir uygulama tarafından sağlanabilir. .

Bu çözüm önemsiz durumlar için iyi çalışır. Bununla birlikte, gözlemcilerin bazılarının [Serializable] olması ve korunmasının gerekmesi mümkündür. Bunu nasıl halledeyim?

Çözümler ben düşünüyorum:

  • tam ISerializable - Sipariş seri bir sürü kod yazma gerektirir, bu
  • [OnSerializing] ve [OnDeserializing] elle PropertyChanged seri hale getirmek özellikleri kullanılarak yapmamayı tercih ediyorum - ama o yardımcı yöntemler (SerializationInfo yaptığı)

cevap

12

Sen righ konum AFAIK seri veri depolamak etmeyen, sadece SerializationContext sağlamak Bu ilk seçenek daha fazla iş. Potansiyel olarak size daha verimli bir uygulama sunarken, varlıklarınızı çok daha karmaşık hale getirecektir. ISerializable, 'u uygulayan bir temel Entity sınıfına sahipseniz, tüm alt sınıfların seri hale getirme işlemini manuel olarak gerçekleştirmesi gerektiğini düşünün!

çalışmak için ikinci seçeneği almak için hile, serileştirilebilir olmayan olarak olay işaretleme devam etmesi, ancak serileştirilebilir olduğunu bir ikinci alanı varsa ve uygun seri kancalar sırasında kendinizi doldurmak olduğunu etmektir. İşte sadece nasıl size göstermek için yazdığı bir örnektir: Zengin L. ile Anlaştı

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

invocation.Target (anonim delegeler için) boş olabilir, bu – skolima

+0

için kontrol ettiğinizden emin olun Bu olayların XmlSerializer üzerinde hiçbir etkisi yoktur (iyi ol, ben sadece çalışmak için Remoting gerekiyordu). – skolima

+0

OnSerializing ve OnDeserialized özel olmalı, bunları açığa çıkarmaya gerek yok. – skolima

1

[field: NonSerialized] Bir Mülkü'yle bir nesne seri hale ile ilgili bir sorun çözer bildirim inşa değişti Pasaj altın kesin. . Teşekkürler

İlgili konular