我可以在不实现IXmlSerializable的情况下为XmlSerializer提供自定义序列化吗?

我们正在使用XmlSerializer ,我想为某些类提供自定义序列化。 但是,我并不总是能够修改有问题的类的源代码,否则我可以让它实现IXmlSerializable 。 有没有办法做到这一点?

这是代理反序列化帮助器的一个简单示例:

给定一种我们无法直接控制类级别序列化的类型:

 public sealed class Class //contrived example { public string Property {get;set;} } 

我们需要反序列化的xml:

  Value  

您可以创建一个代理类型来手动处理目标类型的反序列化过程,如下所示:

 [XmlRoot("Class")] // <-- Very important public sealed class ClassSerializerProxy : IXmlSerializable { public Class ClassValue {get;set;} public System.Xml.Schema.XmlSchema GetSchema(){return null;} public void WriteXml(System.Xml.XmlWriter writer){} public void ReadXml(System.Xml.XmlReader reader) { var x = XElement.ReadFrom(reader) as XElement; this.ClassValue = new Class(); //again this is a simple contrived example this.ClassValue.Property = x.XPathSelectElement("Property").Value; } } 

用法是:

 void Main() { // get the xml value somehow var xdoc= XDocument.Parse(@"Value"); // deserialize the xml into the proxy type var proxy = Deserialize(xdoc); // read the resulting value var value = proxy.ClassValue; } public object Deserialize(XDocument xmlDocument, Type DeserializeToType) { XmlSerializer xmlSerializer = new XmlSerializer(DeserializeToType); using (XmlReader reader = xmlDocument.CreateReader()) return xmlSerializer.Deserialize(reader); } 

现在抛出一些generics和扩展方法,我们可以为最终(EXCEPT EXCEPTION HANDLING)版本清理调用站点:

用法:

 void Main() { var xml = @"Value"; var value = xml.DeserializeWithProxy(); value.Dump(); } 

您的实例类型:

 public sealed class Class { public string Property {get;set;} } 

代理类型必须实现的接口

 public interface ISerializerProxy where TInstanceType : class { TInstanceType Value { get; } } 

示例代理现在实现了新接口

 [XmlRoot("Class")] public sealed class ClassSerializerProxy : IXmlSerializable, ISerializerProxy { public Class Value {get;set;} public System.Xml.Schema.XmlSchema GetSchema(){return null;} public void WriteXml(System.Xml.XmlWriter writer){} public void ReadXml(System.Xml.XmlReader reader) { var x = XElement.ReadFrom(reader) as XElement; this.Value = new Class(); this.Value.Property = x.XPathSelectElement("Property").Value; } } 

反序列化方法现在是string的扩展方法,可以与任何代理类型一起使用。

 public static class ExtensionMethods { public static TInstanceType DeserializeWithProxy(this string xml) where TProxyType : ISerializerProxy where TInstanceType : class { using (XmlReader reader = XDocument.Parse(xml).CreateReader()) { var xmlSerializer = new XmlSerializer(typeof(TProxyType)); return (xmlSerializer.Deserialize(reader) as ISerializerProxy).Value; } } }