2016-06-07 29 views
1

我需要de/serialize對象。但是,有時我需要以某種方式和其他方式序列化它們。De/Serialization模板

實施例:

public interface I : ISerializable { 

    String X { get; set; } 
    String Y { get; set; } 

} 

public class A : I 
{ 
    String X {...} 
    String Y {...} 
    String MyZ { ... } 
} 

public class B : I 
{ 
    String X {...} 
    String Y {...} 
    String MyS { ... } 
} 

有時我需要只使用X字段序列化一個A aB b對象,其它時候我只需要序列Y字段。

請認識到這是一個小例子。實際情況下,真正存在的是我只想保存一些基本信息的對象,其他時間我需要保存其他字段。

這就像應用序列化模板。 任何想法?

編輯 相反的:

var f = new BinaryFormatter(); 
f.Context = new StreamingContext(StreamingContextStates.All, new []{ "X", "Y" }); 

用途:

var f = new BinaryFormatter(); 
f.Context = new StreamingContext(StreamingContextStates.All, TemplatesEnum.Template1); 

所以,每一個對象是resposible爲自己以便根據TemplatesEnum值序列化本身。

+0

看看'[XmlIgnore]'屬性 –

+1

你需要序列化它怎麼樣? XML? JSON?二進制? –

回答

1

一種解決方案是實現ISerializable與服用StreamingContext優點:

public enum TemplatesEnum 
{ 
    Template1, 
    Template2, 
} 

[Serializable] 
public class A : I 
{ 
    public String X { get; set; } 
    public String Y { get; set; } 
    public String MyZ { get; set; } 

    public A() {} 

    // Special ctor for deserialization 
    public A(SerializationInfo info, StreamingContext context) 
    { 
     // Ignore context while deserializing. 

     foreach (SerializationEntry entry in info) 
     { 
      switch (entry.Name) 
      { 
       case "X": 
        X = (string)entry.Value; 
        break; 

       case "Y": 
        Y = (string)entry.Value; 
        break; 

       case "MyZ": 
        MyZ = (string)entry.Value; 
        break; 
      } 
     } 
    } 

    // ISerializable implementation 
    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     TemplatesEnum templ = (TemplatesEnum)context.Context; 

     // Determin which properties should be serialized depending on the context. 
     switch(templ) 
     { 
      case TemplatesEnum.Template1: 
       info.AddValue("X", X); 
       break; 

      case TemplatesEnum.Template2: 
       info.AddValue("X", X); 
       info.AddValue("Y", Y); 
       break; 
     } 
    } 
} 

(供參考:nameof(X)優選字面"X"後C#6)

然後設置TemplatesEnum PARAM到IFormatter.Context序列化時:

class Program 
{ 
    static void Main(string[] args) 
    { 
     A obj = new A() { X = "foo", Y = "bar", MyZ = "baz" }; 

     var f = new BinaryFormatter(); 

     // Serialize depending on a TemplateEnum param. 
     f.Context = new StreamingContext(StreamingContextStates.All, TemplatesEnum.Template1); 

     using (var stm = new FileStream("somefile.bin", FileMode.Create)) 
     { 
      f.Serialize(stm, obj); 
     } 

     // Deserialize 
     using (var stm = new FileStream("somefile.bin", FileMode.Open)) 
     { 
      A des = f.Deserialize(stm) as A; 
     } 
    } 
} 
+0

好的。我得到了我可以使用'StreamingContext'對象。到目前爲止,我已經能夠猜到你的方法是'Main'類提供哪些字段被de/serialize,所以外部類提供這些信息。我猜測每個班都在爲自己負責。我編輯了這篇文章。 – Jordi

+0

也許它幾乎是一樣的。在更新我的答案之前,讓我問你一個問題。反序列化時,你需要一個TemplateEnum參數嗎?或從序列化數據簡單反序列化? – Ripple

+0

我打算使用'TemplateEnum'參數來設置每個對象的序列化方式。 – Jordi

0

將對象序列化到文件的一種方法是使用BinaryFormatter類。你應該在你的類中包含屬性[Serializable()]。如果你不想保留你的類的特定領域,你也可以使用[NonSerialized]屬性。您還可以使用OnSerialized屬性控制序列化過程,以及您在下面的示例中看到的另一個過程。您可以使用多個Formatter,這取決於您希望如何將數據保存到xml格式,json格式或具有特定格式的文件。

[Serializable] 
public class MyObject 
{ 
    public string n1; 
    [NonSerialized] public int n2; 
    public String str; 

[OnSerializing()] 
internal void OnSerializingMethod(StreamingContext context) 
{ 
    n1= "This value went into the data file during serialization."; 
} 

[OnSerialized()] 
internal void OnSerializedMethod(StreamingContext context) 
{ 
    n1 = "This value was reset after serialization."; 
} 

[OnDeserializing()] 
internal void OnDeserializingMethod(StreamingContext context) 
{ 
    n1 = "This value was set during deserialization"; 
} 

[OnDeserialized()] 
internal void OnDeserializedMethod(StreamingContext context) 
{ 
    n1 = "This value was set after deserialization."; 
} 
} 

var obj = new MyObject(); 
// Open a file and serialize the object into binary format. 
Stream stream = File.Open("DataFile.txt", FileMode.Create); 
BinaryFormatter formatter = new BinaryFormatter(); 
formatter.Serialize(stream, obj); 
// Deserialize the object from the data file. 
obj = (TestSimpleObject)formatter.Deserialize(stream);