C# 如何序列化“的多个成员”;这";

C# 如何序列化“的多个成员”;这";,c#,serialization,this,C#,Serialization,This,我有一个包含几个成员的类,我想序列化以存储状态 但是,我希望从类本身内部序列化,而不是通过某个外部类将其提供给格式化程序 所以理论上我想做一些类似的事情: [DataContract] class MyClass { [DataMember] private MyCompoundClass _someCompoundField; [DataMember] private int _someOtherField; private void SaveSta

我有一个包含几个成员的类,我想序列化以存储状态

但是,我希望从类本身内部序列化,而不是通过某个外部类将其提供给格式化程序

所以理论上我想做一些类似的事情:

[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文件中有两个根节点

如何创建“包装器”节点来包装字段。还是我应该用别的方法来做这件事


非常感谢,

您是否绑定到特定的序列化程序?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);
        }
    }
}
注意在成员属性上添加了
Order=n
;这是因为protobuf在字段/属性上使用数字标识符,并且需要一种方法来选择它们。您还可以使用特定于项目的
[ProtoContract]
/
[ProtoMember(n)]
属性,但它也可以与WCF属性一起使用(如图所示)


Merge
也可在非通用2.0 API上使用-但是您可以将
作为参数传递给
反序列化

将反序列化方法置于静态方法中:

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

要仅序列化某些对象,请注释某些字段以避免序列化,或者创建一个仅包含要序列化的字段的超类或接口。

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

  • 反序列化一个新的
    MyClass
    ,并将成员复制到
  • LoadState
    设为静态,并让它返回反序列化的
    MyClass
  • 使用不同的序列化机制,可以实现您想要的功能

  • 您可以在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;
             }
        }
    

    是的,我考虑过这样做,不过看起来很乱-/@GazTheDestroyer:它会成功的;)但是,如果您想稍微组织一下,您可以在MyClass中添加方法,比如
    private void FromMyClass(MyClass MyClass){/*此处将值从所需对象复制到当前实例*/}
    2),因为许多其他对象都引用了该实例,所以它不应该更改。1) 看起来凌乱和冗长(但我想不超过我的手动序列化)3)将是我的选择,但我对.Net不够熟悉,还不知道还有什么其他选择。如果好处可以证明这一努力的合理性,1)的混乱可能隐藏在基于反射的API后面。是的,最后还是1。仍然感觉不对,但这是迄今为止最快的方法。:)不幸的是,对象实例必须保持不变,因为其他代码持有对它的引用。