繁体   English   中英

XML序列化基类,而无需了解派生类

[英]XML serialize base class without knowing derived class

我知道,如果传入的类型与创建序列化器时的类型不匹配,则XmlSerializer将引发异常。

我的问题是:是否可以在不知道派生类型的情况下序列化基本类型? 考虑这种情况:

以下类位于顶级域中,几乎没有依赖项

public class Serializer
{
    private static string Serialize(Base baseData)
    {
        var serializer = new XmlSerializer(typeof(Base));
        var sb = new StringBuilder();
        using (var writer = XmlWriter.Create(sb))
        {
            serializer.Serialize(writer, baseData);
        }
        return sb.ToString();
    }

    private static string Deserialize(...) { ... }
}

public class Base
{
    public string Name { get; set; }
}

以下派生类对UI组件,组成等有更多依赖关系 (稍后会对此进行更多介绍):

[Export(typeof(IMyComponent))]
public class Derived : Base, IMyComponent, INotifyPropertyChanged
{
    public new string Name
    { 
        get { return base.Name; }
        set
        {
            base.Name = value;
            NotifyPropertyChanged("Name");
        }
    }
}

如果我这样调用序列化器:

Base myData = new Derived();
myData.Name = "Foo bar";
Serializer.Serialize(myData);

因为我传入了Derived ,所以它引发了异常,即使参数和序列化程序已显式设置为Base 我只想序列化Base ,我不在乎Derived任何内容。

我的目标是使用UI创建派生类,但仅序列化基类 原因是我在一个单独的程序集中反序列化XML,该程序集不得包含.NET框架之外的其他依赖项。 将序列化程序和基础对象重新创建/复制到此隔离的程序集中,以便名称空间和类型匹配,以便在进行反序列化时,将正确地反序列化类型。 但是我不能包含Derived的副本,因为它依赖于UI,MEF,其他第三方库等。

因此,即使传递了派生类,如何强制序列化程序对基类进行序列化? 同样,我不在乎是否会丢失Derived的信息,我所关心的只是Base

一种可能的解决方案是:

public class Serializer
{
    public static string Serialize(Base baseData)
    {
        var baseType = baseData.GetType().BaseType;
        var baseTypeFieldInfo = baseType.GetProperties();
        var newBaseInstance = new Base();
        var newBaseInstanceType = newBaseInstance.GetType();
        //ONLY gets public properties but could be applied to fields
        var newBaseTypeFieldInfo = newBaseInstanceType.GetProperties();
        foreach (var bt in baseTypeFieldInfo)
        {
            foreach (var nbt in newBaseTypeFieldInfo)
            {
                if (nbt.Name == bt.Name)
                {
                    nbt.SetValue(newBaseInstance, bt.GetValue(baseData, null), null);
                }
            }
        }
        var serializer = new XmlSerializer(typeof(Base));
        var sb = new StringBuilder();
        using (var writer = XmlWriter.Create(sb))
        {
            serializer.Serialize(writer, newBaseInstance);
        }
        return sb.ToString();
    }
}

public class Base
{
    public string Name { get; set; }
}


public class Derived : Base
{

    public string AnotherName { get; set; }

    public new string Name
    {
        get { return base.Name; }
        set { base.Name = value; }
    }
}

由于您只想序列化Base属性,因此您必须创建Base实例并从派生类型映射属性。 序列化器被编程为很聪明,有时就您而言太聪明了。

查看AutoMapper或手动进行。

public class Serializer
{
    private static string Serialize(Base baseData)
    {
        var mappedBase = new Base();
        // Do mapping
        mappedBase.Foo = baseData.Foo;

        var serializer = new XmlSerializer(typeof(Base));
        var sb = new StringBuilder();
        using (var writer = XmlWriter.Create(sb))
        {
            serializer.Serialize(writer, mappedBase);
        }
        return sb.ToString();
    }

    private static string Deserialize(...) { ... }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM