XmlSerializer - 忽略继承的不可序列化成员 [英] XmlSerializer - Ignoring inherited unserializable member

查看:28
本文介绍了XmlSerializer - 忽略继承的不可序列化成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你有两个类,一个继承另一个,子类需要用 XmlSerializer 进行序列化/反序列化.但是,父级包含一个不可序列化的成员,比如字典.

Assume you have two classes, one inherits the other and the child needs to be serialized / deserialized with XmlSerializer. However, the parent contains a member that is not serializeable, say a dictionary.

public class Parent {

    public Dictionary<string, int> dictionary;
}

父类是用于许多其他脚本的库.它不能被修改.现在子类只包含可序列化的成员:

The parent class is a library used for many other scripts. It cannot be modified. Now the child class contains only serializable members:

public class Child : Parent {

    [XmlElement]
    public int foo;

}

尝试调用序列化程序时,我收到一条错误消息,指出该字典不可序列化.当尝试在 JSON 中进行序列化时,我设法以警告的代价逃脱了.我刚刚创建了另一个具有相同名称和类型的成员,并使用了 ScriptIgnore:

When trying to call the serializer, I receive an error saying that the dictionary is not serializable. When trying to serialize in JSON, I managed to get away by the price of a warning. I just created another member with the same name and type, and used ScriptIgnore:

public class Child : Parent {

    public int foo;

    [ScriptIgnore]
    public Dictionary<string, int> dictionary;

}

我在这里再次尝试了相同的技巧(通过使用 XmlIgnore)但是效果不佳,错误是一样的.我设法解决这个问题的唯一方法是创建单独的类,这些类只为 xml 反/序列化提供服务,然后将值复制回适当的位置.

I tried the same trick again here (by using XmlIgnore) but that didn't work on very well, the error was the same. The only way I managed to go through this is create separate classes that will only serve xml de/serializing and then copy the values back into the appropriate place.

有人知道更好的方法吗?我可以让 XmlSerializer 以任何方式忘记父字典吗?

Does anyone know a better way around this? Can I make XmlSerializer forget about the parent dictionary in any way?

推荐答案

我要说的第一件事,并且总是说:如果序列化现有模型变得棘手 - 甚至有点尴尬,那么 停止这样做.花 2 分钟时间创建一个单独的 DTO 模型,即仅为序列化目的而创建的模型(实际上,甚至可能针对特定的序列化程序量身定制).现在您放置了完全正确的类型、正确的成员、正确的属性和正确的布局.您需要做的就是添加一些转换方法 - 静态转换运算符在这里很有效.所以我想说的是:创建一个 ParentDtoChildDto(你的名字可能会有所不同);这将需要 3 分钟,而且效果很好.

The very first thing I would say, and always say: if serializing an existing model gets tricky - even remotely awkward, then stop doing that. Take 2 minutes to create a separate DTO model, i.e. a model created solely for the purposes of serialization (and indeed, perhaps even tailored to a specific serializer). Now you put the exact right types, right members, right attributes, and right layout. All you need to do is add some conversion methods - static conversion operators work great here. So what I would say is: create a ParentDto and ChildDto (your names may vary); it'll take 3 minutes, and it'll work great.

现在,回到问题......

Now, back to the question...

XmlSerializer 查看输入的声明类;对于属性和条件序列化,不:此时我们无法将它们添加到类型模型中.但是还有另一种选择 - 您可以使用 XmlAttributeOverrides 来假装字典成员上有一个 [XmlIgnore].但是,一些重要的警告:

XmlSerializer looks at the declaring class for input; for both attributes and conditional serialization, no: we can't add those into the type model at this point. But there is another option - you can use XmlAttributeOverrides to pretend that there was an [XmlIgnore] on the dictionary member. However, some important caveats:

  • XmlAttributeOverrides API 使用起来有点麻烦(参见 MSDN 示例)
  • 关键您只执行此一次,然后存储和重复使用XmlSerializer你以这种方式创造;基本上,如果你这样做,它会在你每次new序列化程序时创建一个新的动态程序集,并且程序集永远不会卸载,所以你会出血记忆;请注意,简单 用法(new XmlSerializer(someType) 等)为此具有内置缓存;但是 XmlAttributeOverrides 用法没有
  • the XmlAttributeOverrides API is a bit of a faff to use (see MSDN for an example)
  • it is critical that you only do this once, and then store and re-use the XmlSerializer that you create this way; basically, if you don't do this, it will create a new dynamic assembly every time you new a serializer, and assemblies never unload, so you will haemorrhage memory; note that the simple usage (new XmlSerializer(someType) etc) has an inbuilt cache for this; but the XmlAttributeOverrides usage does not

但同样,所有这些与 XmlAttributeOverrides 相关的工作比仅仅创建一个基本的 DTO

But again, all this messing with XmlAttributeOverrides is a lot more work than just creating a basic DTO

使用XmlAttributeOverrides的例子:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
public class Parent {
    public Dictionary<string, int> WantToIgnoreThis { get; set; }
}    
public class Child : Parent {
    public int Foo { get; set; }
}
static class Program
{
    static readonly XmlSerializer customSerializer;

    static Program()
    {
        var xao = new XmlAttributeOverrides();
        xao.Add(typeof(Parent), "WantToIgnoreThis", new XmlAttributes {
            XmlIgnore = true
        });
        customSerializer = new XmlSerializer(typeof(Child), xao);
    }
    static void Main()
    {
        //var ser = new XmlSerializer(typeof(Child));
        // ^^ this would fail

        customSerializer.Serialize(Console.Out, new Child {
            Foo = 123
        });
    }
}

特别注意 static 字段是如何用于缓存序列化程序的.

Note in particular how the static field is used to cache the serializer.

这篇关于XmlSerializer - 忽略继承的不可序列化成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆