如何序列化“this”的多个成员

时间:2011-06-21 11:01:51

标签: c# serialization this

我有一个班级,有几个成员,我想序列化以存储州。

但是,我想从WITHIN本身序列化,而不是通过一些外部类将其提供给格式化程序。

所以理论上我想做的事情是:

[DataContract]
class MyClass
{
    [DataMember]
    private MyCompoundClass _someCompoundField;

    [DataMember]
    private int _someOtherField;

    private void SaveState()
    { 
         using (Stream stream = GetStream())
         {
             DataContractSerializer serialiser = new DataContractSerializer(typeof(MyClass));
             serialiser.WriteObject(stream, this);
         }
    }

    private void LoadState()
    { 
         using (Stream stream = GetStream())
         {
             DataContractSerializer serialiser = new DataContractSerializer(typeof(MyClass));
             this = (MyClass)serialiser.ReadObject(stream);
         }
    }
}

现在显然是

 this = (MyClass)serialiser.ReadObject(stream);

是胡说八道,但你可以看到我正在尝试做什么。我想从类中序列化我的类的两个字段。 (我正在使用WCF序列化程序,但我认为如果我使用XmlSerializer,这将是相同的。)

我尝试通过自己序列化每个字段来正确实现这一点:

private void SaveState()
{ 
    using (Stream stream = GetStream())
    {
        //serialise field 1
        DataContractSerializer serialiser = new DataContractSerializer(typeof(MyCompoundClass));
        serialiser.WriteObject(stream, _someCompoundField);

        //serialise field 2
        serialiser = new DataContractSerializer(typeof(int));
        serialiser.WriteObject(stream, _someOtherField);
    }
}

现在这可以作为一个保存,但是当我来回读取文档时,由于XML文件中有两个根节点,因此抛出异常。

如何创建我的“包装器”节点来包装我的字段。或者还有其他方法我应该这样做吗?

非常感谢,

4 个答案:

答案 0 :(得分:1)

我还没有看到任何修改现有对象的内置反序列化方法,而不是返回一个新对象。我看到你的选择是:

  1. 反序列化新的MyClass并将成员复制到
  2. LoadState设为静态,并让其返回反序列化的MyClass
  3. 使用可以执行您想要的其他序列化机制

答案 1 :(得分:1)

你可以在你的LoadState上执行:

    private void LoadState()
    { 
         using (Stream stream = GetStream())
         {
             DataContractSerializer serialiser = new DataContractSerializer(typeof(MyClass));
             MyClass deserialized = (MyClass)serialiser.ReadObject(stream);

             this._someCompoundField = deserialized._someCompoundField;
             this._someOtherField = deserialized._someOtherField;
         }
    }

答案 2 :(得分:0)

您是否与特定的序列化程序绑定? protobuf-net支持该用例,例如:

[DataContract]
class MyClass
{
    [DataMember(Order = 1)]
    private MyCompoundClass _someCompoundField;

    [DataMember(Order = 2)]
    private int _someOtherField;

    private void SaveState()
    {
        using (Stream stream = GetStream())
        {
            ProtoBuf.Serializer.Serialize(stream, this);
        }
    }

    private void LoadState()
    {
        using (Stream stream = GetStream())
        {
            ProtoBuf.Serializer.Merge(stream, this);
        }
    }
}

注意在member-attributes上添加Order = n;这是因为protobuf在字段/属性上使用数字标识符,并且需要一种方法来选择它们。您还可以使用项目特定的[ProtoContract] / [ProtoMember(n)]属性,但它也适用于WCF(如图所示)。

Merge也适用于非通用2.0 API - 但您将this作为参数传递给Deseroalize而不是

答案 3 :(得分:0)

将反序列化方法放在静态方法中:

class MyClass
{
    public static MyClass LoadState()
    { 
         // Deserialize, and return the new MyClass instance.
    }
}

要序列化一些对象,注释一些字段以避免序列化,或者仅使用要序列化的字段创建超类或接口。