c# – 我可以提供XmlSerializer的自定义序列化,而不实现IXmlSerializable?

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

解决方法

这是一个简单的代理反序列化助手的例子:

给定一个类型,我们不能直接控制在类级别的序列化:

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

而我们需要反序列化的xml:

<Class>
  <Property>Value</Property>
</Class>

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

[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(@"<Class><Property>Value</Property></Class>");

    // deserialize the xml into the proxy type
    var proxy = Deserialize<ClassSerializerProxy>(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);
}

现在抛出一些泛型和扩展方法,我们可以清理一下最后一个(EXCEPT EXCEPTION HANDLING)版本的调用站点

用法

void Main()
{
    var xml = @"<Class><Property>Value</Property></Class>";

    var value = xml.DeserializeWithProxy<ClassSerializerProxy,Class>();

    value.Dump();
}

您的实例类型:

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

代理类型必须实现的接口

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

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

[XmlRoot("Class")]
public sealed class ClassSerializerProxy : IXmlSerializable,ISerializerProxy<Class>
{
    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;
    }
}

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

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

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...