XmlSerializer - 忽略继承的不可序列化成员 [英] XmlSerializer - Ignoring inherited unserializable member
问题描述
假设你有两个类,一个继承另一个,子类需要用 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 模型,即仅为序列化目的而创建的模型(实际上,甚至可能针对特定的序列化程序量身定制).现在您放置了完全正确的类型、正确的成员、正确的属性和正确的布局.您需要做的就是添加一些转换方法 - 静态转换运算符在这里很有效.所以我想说的是:创建一个 ParentDto
和 ChildDto
(你的名字可能会有所不同);这将需要 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 younew
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 theXmlAttributeOverrides
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屋!