gpt4 book ai didi

.net - 在 .NET 中序列化数据传输对象

转载 作者:行者123 更新时间:2023-12-04 14:20:50 25 4
gpt4 key购买 nike

我有一组数据传输对象(例如,许多请求、响应消息类,如 MainRequest、MainResponse、ShutDownRequest、ShutDownResponse)随着项目的发展,新类不断出现。这些类必须从和到 进行(反)序列化。具有不同公共(public) XSD 的各种 XML 格式 .随着项目的发展,新的 XML 格式也随之出现。

我的问题是我将如何围绕这两个要求设计我的类和接口(interface),尤其是我应该放置实际(反)序列化逻辑的地方。我是否应该编写一个可以获取各种 DTO 实例并知道如何序列化它们的静态服务?当新类(class)到来时,我必须触摸每个 FormatXSeriaizer 并添加新的覆盖。随着新格式的出现,我只需要编写新的 FormatXSerializer 类。

FormatASerializer.Serialize(XmlWriter writer, MainResponse r);
FormatASerializer.Serialize(XmlWriter writer, ShutDownResponse r);
FormatBSerializer.Serialize(XmlWriter writer, MainResponse r);
FormatBSerializer.Serialize(XmlWriter writer, ShutDownResponse r);

或者 DTO 自己应该知道如何去做。所以我把所有东西都放在一个地方——每个 DTO 类。随着新的 DTO 类的出现,它们只需要实现各种格式的序列化。随着新格式的出现,我必须接触每个 DTO 类。
myMainRequestInstace.Serialize(FormatTypeEnum type, XmlWriter writer);

还是有完全不同的方法?我是否应该为序列化引入一个通用接口(interface)并进行一些控制反转,以便我可以在运行时加载新的格式序列化程序?

什么设计模式可以在这里指导我?

我可以研究 .NET 世界中的哪些开源代码以了解有关该主题的不同方法?

编辑:
我知道框架中存在的一般序列化技术。我的问题更倾向于尊重两个要求的类设计:随着项目的发展,多种 xml 格式和多种 DTO(消息类型)不断出现。

最佳答案

最好的方法是这样的,这是我最喜欢的方法:

公共(public)类 SomeClass : ISerializable{
私有(private) float _fVersion;
……
公共(public) float 版本{
得到 { 返回 this._fVersion; }
}

私有(private) SomeClass(SerializationInfo 信息,StreamingContext 上下文){
bool 博克 = 假;
this._fVersion = info.GetSingle("versionID");
if (this._fVersion == 1.0F) bOk = this.HandleVersionOnePtZero(info, context);
if (this._fVersion == 1.1F) bOk = this.HandleVersionOnePtOne(info, context);

if (!bOk) throw new SerializationException(string.Format("SomeClass: 无法处理此版本 {0}。", this._fVersion.ToString()));
}
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("versionID", this._fVersion);
如果(this._fVersion == 1.0F){
info.AddValue("someField", ...);
info.AddValue("anotherField", ...);
}
如果(this._fVersion == 1.1F){
info.AddValue("someField1", ...);
info.AddValue("anotherField2", ...);
}
}
private bool HandleVersionOnePtZero(SerializationInfo info, StreamingContext context) {
bool rvOk = 假;
... = info.GetValue("someField");
... = info.GetValue("anotherField");
}

private bool HandleVersionOnePtOne(SerializationInfo info, StreamingContext context) {
bool rvOk = 假;
... = info.GetValue("someField1");
... = info.GetValue("anotherField2");
}

}

这就是我如何对二进制数据的序列化进行更严格的控制并提高版本的方式。现在,你们中的那些人会指出,已经有一个功能可以做到这一点,但是来自 .NET 1.1,好吧,旧习惯很难改掉。

请注意,在上面的代码示例中,我使用了两种不同的方法 HandleVersionOnePtZeroHandleVersionOnePtOne处理不同版本的序列化流。通过这样做,我有更大程度的灵 active ,说如果字段 someField需要改变吗?另外,请注意 _fVersion字段是可序列化例程首先要做的第一件事,然后检查字段的版本并决定使用哪个字段。

唯一的问题是,如果您更改命名空间,那么您将难以反序列化数据,但您可以使用 SerializationBinder 类作为示例:

公共(public)类 SomeClassBinder : System.Runtime.Serialization.SerializationBinder {
公共(public)覆盖类型 BindToType(字符串 assemblyName,字符串 typeName){
类型 typeToDeserialize = null;
尝试 {
//对于要反序列化的每个 assemblyName/typeName
//不同的类型,将 typeToDeserialize 设置为所需的类型。
string assemVer1 = System.Reflection.Assembly.GetExecutingAssembly().FullName;
if (assemblyName.StartsWith("foobar")) {
程序集名称 = assemVer1;
typeName = "fubar"+ typeName.Substring(typeName.LastIndexOf("."), (typeName.Length - typeName.LastIndexOf(".")));
}
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
} 捕捉(System.Exception ex1){
抛出 ex1;
} 最后 {
}
返回类型ToDeserialize;
}
}

它会被这样调用:
BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new SomeClassBinder();
SomeClass sc = bf.Deserialize(stream);//假设流被声明并打开

希望这可以帮助

关于.net - 在 .NET 中序列化数据传输对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2121424/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com