bit*_*onk 6 .net serialization class-design
我有一组数据传输对象(例如很多请求,响应消息类,如MainRequest,MainResponse,ShutDownRequest,ShutDownResponse)随着项目的发展,新类不断涌现.这些类必须(使用不同的公共XSD从各种XML格式序列化).随着项目的发展,新的XML格式也随之而来.
我的问题是如何围绕这两个要求设计我的类和接口,特别是在我应该放置实际(de)serration逻辑的地方.我应该编写一个可以接受各种DTO实例的静态服务,知道如何序列化它们吗?当新课程出现时,我必须触摸每个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);
Run Code Online (Sandbox Code Playgroud)
或者DTO自己应该知道如何去做.所以我把它放在一个地方 - 每个DTO课程.随着新的DTO课程的出现,他们只需要实现各种格式的序列化.随着新格式的出现,我必须触及每个DTO课程.
myMainRequestInstace.Serialize(FormatTypeEnum type, XmlWriter writer);
Run Code Online (Sandbox Code Playgroud)
还是有完全不同的方法?我是否应该为序列化引入一个通用的接口并且有一些控制反转,所以我可以在运行时加载新格式的序列化器?
什么设计模式可以指导我在这里?
我可以研究.NET世界中的哪些开源代码来查看有关此主题的不同方法?
编辑:我知道框架中存在的一般序列化技术.我的问题更侧重于尊重这两个要求的类设计:多个xml格式和多个DTO(消息类型)随着项目的发展而不断涌现.
最好的方法是这样的,这是我最喜欢的方法:
public class SomeClass : ISerializable{
private float _fVersion;
....
public float Version {
get { return this._fVersion; }
}
private SomeClass(SerializationInfo info, StreamingContext context) {
bool bOk = false;
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: Could not handle this version {0}.", this._fVersion.ToString()));
}
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("versionID", this._fVersion);
if (this._fVersion == 1.0F) {
info.AddValue("someField", ...);
info.AddValue("anotherField", ...);
}
if (this._fVersion == 1.1F) {
info.AddValue("someField1", ...);
info.AddValue("anotherField2", ...);
}
}
private bool HandleVersionOnePtZero(SerializationInfo info, StreamingContext context) {
bool rvOk = false;
... = info.GetValue("someField");
... = info.GetValue("anotherField");
}
private bool HandleVersionOnePtOne(SerializationInfo info, StreamingContext context) {
bool rvOk = false;
... = info.GetValue("someField1");
... = info.GetValue("anotherField2");
}
}
这就是我如何对二进制数据的序列化实施更严格的控制并提升版本.现在,你们中的那些人会指出已经有一个功能可以做到这一点,但是来自.NET 1.1,老习惯很难.
注意如何代码示例中上述我使用了两种不同的方法HandleVersionOnePtZero和HandleVersionOnePtOne用于处理不同版本的串行化流的.通过这种方式,我有更大程度的灵活性,如果该领域someField需要改变怎么办?另外,请注意该_fVersion字段是可序列化例程首先执行的操作,然后检查字段的版本并决定使用哪个字段.
唯一的问题是,如果您更改命名空间,那么您将难以反序列化数据,但您可以使用SerializationBinder类作为示例:
public class SomeClassBinder : System.Runtime.Serialization.SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
Type typeToDeserialize = null;
try {
// For each assemblyName/typeName that you want to deserialize to
// a different type, set typeToDeserialize to the desired type.
string assemVer1 = System.Reflection.Assembly.GetExecutingAssembly().FullName;
if (assemblyName.StartsWith("foobar")) {
assemblyName = assemVer1;
typeName = "fubar" + typeName.Substring(typeName.LastIndexOf("."), (typeName.Length - typeName.LastIndexOf(".")));
}
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
} catch (System.Exception ex1) {
throw ex1;
} finally {
}
return typeToDeserialize;
}
}
it would be called like this:
BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new SomeClassBinder();
SomeClass sc = bf.Deserialize(stream); // assume stream is declared and open
希望这可以帮助
| 归档时间: |
|
| 查看次数: |
6708 次 |
| 最近记录: |