简体   繁体   English

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

[英]XML serialize base class without knowing derived class

I know that an XmlSerializer will throw an exception if the passed in type does not match the type from when the serializer was created. 我知道,如果传入的类型与创建序列化器时的类型不匹配,则XmlSerializer将引发异常。

My question is: Is it possible to serialize a base type without knowing the derived type? 我的问题是:是否可以在不知道派生类型的情况下序列化基本类型? Consider this scenario: 考虑这种情况:

The following classes are in a top-level domain and have few or no dependencies : 以下类位于顶级域中,几乎没有依赖项

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; }
}

The following derived class has additional dependencies on things like UI components, composition, etc. (more on this later): 以下派生类对UI组件,组成等有更多依赖关系 (稍后会对此进行更多介绍):

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

If I invoke the serializer like this: 如果我这样调用序列化器:

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

It throws an exception because I passed in a Derived , even though the parameters and serializer are explicitly set to Base . 因为我传入了Derived ,所以它引发了异常,即使参数和序列化程序已显式设置为Base All I want is to serialize Base , I don't care about whatever is in Derived . 我只想序列化Base ,我不在乎Derived任何内容。

My goal here is to create the derived class with a UI, but only serialize the base class . 我的目标是使用UI创建派生类,但仅序列化基类 The reason is that I am deserializing the XML in a separate assembly that must not contain additional dependencies beyond the .NET framework. 原因是我在一个单独的程序集中反序列化XML,该程序集不得包含.NET框架之外的其他依赖项。 The serializer and base objects are recreated/copied into this isolated assembly so that the namespaces and types will match, so that when deserialization occurs, the types will be deserialized correctly. 将序列化程序和基础对象重新创建/复制到此隔离的程序集中,以便名称空间和类型匹配,以便在进行反序列化时,将正确地反序列化类型。 But I can't include a copy of Derived because it has dependencies on UI, MEF, other third party libraries, etc. 但是我不能包含Derived的副本,因为它依赖于UI,MEF,其他第三方库等。

So, how can I force the serializer to serialize the base class even if I pass in a derived class? 因此,即使传递了派生类,如何强制序列化程序对基类进行序列化? Again, I don't care if I lose the information in Derived , all I am concerned about is Base . 同样,我不在乎是否会丢失Derived的信息,我所关心的只是Base

One possible solution would be: 一种可能的解决方案是:

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; }
    }
}

Since you are looking to only serialize the Base properties, you have to create an instance of Base and map the properties from the derived type. 由于您只想序列化Base属性,因此您必须创建Base实例并从派生类型映射属性。 Serializers are programmed to be smart, sometimes too smart in your case. 序列化器被编程为很聪明,有时就您而言太聪明了。

Look into AutoMapper or just do it manually. 查看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.

相关问题 序列化派生的xml到C#中的基类 - serialize derived xml to base class in C# 在一个派生类中序列化基类属性,而无需在第二个序列化类中对其进行序列化 - serialize base class property in one derived class without serializing it in second serialize class 无法将派生类序列化为XML - Unable to serialize a derived class to XML 具有序列化派生类能力的基类 - Base Class with Ability to Serialize Derived Class 序列化/反序列化派生类为基类 - Serialize/Deserialize derived class as base class XML序列化:序列化自同一基类派生的自定义类列表,并使用元素的基类名称 - Xml serialization: serialize list of custom classes, derived from the same base class, using base class name for elements 如何用派生类序列化基类 class - How to serialize the base class with derived classes 从基类序列化和反序列化派生类 - Serialize and DeSerialized derived classes from the base class 如何在不事先知道类型的情况下使用XmlSerializer反序列化可能是基类或派生类的对象? - How do I use an XmlSerializer to deserialize an object that might be of a base or derived class without knowing the type beforehand? 我如何 XML 序列化作为基础 class 并具有 4 个派生类的 object - How can I XML Serialize an object that is the base class and has 4 derived classes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM