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

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(消息类型)随着项目的发展而不断涌现.

t0m*_*13b 5

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

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,老习惯很难.

注意如何代码示例中上述我使用了两种不同的方法HandleVersionOnePtZeroHandleVersionOnePtOne用于处理不同版本的串行化流的.通过这种方式,我有更大程度的灵活性,如果该领域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

希望这可以帮助


Bur*_*urt 0

阅读有关自定义 XML 序列化程序的内容,它们应该能够完成您需要的一切。

关联