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。仍然感觉不对,但这是迄今为止最快的方法。:)不幸的是,对象实例必须保持不变,因为其他代码持有对它的引用。