2010-02-01 20 views
5

olarak davranan özel bir serileştirme özniteliği nasıl eklenir? EntitySet ve EntityRef sınıflarını içeren db linq nesnelerinin bazı serileştirilmesini yapıyorum..NET, C#: ISerializable arabirimi

Bu sınıfların serileştirilmesiyle başa çıkmak için oldukça kolay bir yol buldum. Bu tür üyelerin düzgün bir şekilde işlemesi için ISerializable (serileştirme için listelere dönüştürmek ve serileştirme üzerine geri almak).

[Serializable] 
[SerializeLinqEntities] 
partial class Person 
{ ... } 

yerine:

partial class Person : ISerializable 
{ 
    public virtual void GetObjectData(SerializationInfo si, StreamingContext ctxt) 
    { 
    EntitySerializer.Serialize(this, typeof(Person), si, ctxt); 
    } 

    protected Person(SerializationInfo si, StreamingContext ctxt) 
    { 
    EntitySerializer.Deerialize(this, typeof(Person), si, ctxt); 
    } 
} 

bunu yapmanın bir yolu var mı yapabileceğim eğer

Ancak, gerçekten güzel olurdu? Seri hale getirme sınıflarını inceledim ve özel serileştirme filtresi rutinlerini (özel özniteliğimi bulabileceğim) kurulumu için herhangi bir yol bulamadım.

Teşekkürler!

+0

IClientFormatterSinkProvider ve IServerFormatterSinkProvider benziyor benim özel SurrogateSelector set ile BinaryFormatter sunmamızı sağlayacaktır. Tekrar teşekkürler Sergey! – marq

+0

Hmm ... öyle görünüyor ki, Microsoft bunu göründüğünden çok daha zorlaştırdı. Aşağıdaki bağlantıya bakın: http://www.123aspx.com/Rotor/RotorSrc.aspx?rot=40027 Sink sağlayıcıları, ortaya çıktığı gibi oldukça karmaşıktır ve yalnızca birini uygulamak kadar basit değildir. Gerçekten, daha iyi bir arayüz API'sinin, ikili seri hale getirme ile arabirim sağlamasını isterdim ... – marq

cevap

7

Evet, bunu ISerializationSurrogate ve ISurrogateSelector arabirimlerini uygulayarak yapabilirsiniz. Böyle

şey:

[AttributeUsage(AttributeTargets.Class)] 
public class SerializeLinqEntities : Attribute 
{ 
} 

public class LinqEntitiesSurrogate : ISerializationSurrogate 
{ 
    public void GetObjectData(
     object obj, SerializationInfo info, StreamingContext context) 
    { 
     EntitySerializer.Serialize(this, obj.GetType(), info, context); 
    } 

    public object SetObjectData(
     object obj, SerializationInfo info, 
     StreamingContext context, ISurrogateSelector selector) 
    { 
     EntitySerializer.Deerialize(obj, obj.GetType(), info, context); 
     return obj; 
    } 
} 


/// <summary> 
/// Returns LinqEntitySurrogate for all types marked SerializeLinqEntities 
/// </summary> 
public class NonSerializableSurrogateSelector : ISurrogateSelector 
{ 
    public void ChainSelector(ISurrogateSelector selector) 
    { 
     throw new NotImplementedException(); 
    } 

    public ISurrogateSelector GetNextSelector() 
    { 
     throw new NotImplementedException(); 
    } 

    public ISerializationSurrogate GetSurrogate(
     Type type, StreamingContext context, out ISurrogateSelector selector) 
    { 
     if (!type.IsDefined(typeof(SerializeLinqEntities), false)) 
     { 
      //type not marked SerializeLinqEntities 
      selector = null; 
      return null; 
     } 
     selector = this; 
     return new LinqEntitiesSurrogate(); 
    } 

} 

[SerializeLinqEntities] 
public class TestSurrogate 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

class Program 
{ 
    static void Main(string[] str) 
    { 

     var ns1 = new TestSurrogate {Id = 47, Name = "TestName"}; 
     var formatter = new BinaryFormatter(); 
     formatter.SurrogateSelector = new NonSerializableSurrogateSelector(); 

     using (var ms = new MemoryStream()) 
     { 
      formatter.Serialize(ms, ns1); 
      ms.Position = 0; 

      var ns2 = (TestSurrogate) formatter.Deserialize(ms); 
      // Check serialization 
      Debug.Assert(ns1.Id == ns2.Id); 
      Debug.Assert(ns1.Name == ns2.Name); 
     } 
    } 
} 
+0

Tam olarak istediğim şey budur (ISurrogateSelector tam olarak aradığım şey). Yani, son soru - otomatik seri hale getirme ile bunu kullanmak için bir yolu var mı? Seri hale getirmem, bir RPC çağrısı (bir MarshalByRefObject kullanarak) aracılığıyla gerçekleşiyor. – marq

+0

+1 "ISerializationSurrogate" hakkında düşünmedim bile çünkü açık bir şekilde belirtilen özellikler. Bu çözümle ilgili tek sorun, 'SurrogateSelector' özelliğini ayarlamak için biçimlendirici örneğine erişiminiz olmadığı zaman gelir. – Rory

+0

WCF'de kolayca vekil kullanabilirsiniz (http://msdn.microsoft.com/en-us/library/ms733064.aspx). .net remoting ile surrogates kullanmıyorum. Belki Özel Lavabolar size yardımcı olabilir (http://www.codeproject.com/KB/IP/customsinks.aspx). –

0

Ne yazık ki, ISerializable, SerializableAttribute yalnızca "bu sınıf seri hale getirilebilir" yazan bir işaretleyici olduğunda, serileştirme işlemini denetlemenizi sağlamak için tasarlanmış bir arabirimdir. Ancak, bu işlevi eklemek için PostSharp gibi bir şeye bakabilirsiniz (CompositionAspect'a bakın).