- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
.NET 中的 XML 序列化通过 XmlSerializer
构造函数的 extraTypes[]
参数允许多态对象。它还允许为实现 IXmlSerializable
的类型自定义 XML 序列化。
但是,我无法将这两个功能结合起来——如这个最小示例所示:
using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace CsFoo
{
public class CustomSerializable : IXmlSerializable
{
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader xr) { }
public void WriteXml(XmlWriter xw) { }
}
class CsFoo
{
static void Main()
{
XmlSerializer xs = new XmlSerializer(
typeof(object),
new Type[] { typeof(CustomSerializable) });
xs.Serialize(new StringWriter(), new CustomSerializable());
}
}
最后一行抛出 System.InvalidOperationException
并显示以下消息:
The type CsFoo.CustomSerializable may not be used in this context to use CsFoo.CustomSerializable as a parameter, return type, or member of a class or struct, the parameter, return type, or member must be declared as type CsFoo.CustomSerializable (it cannot be object). Objects of type CsFoo.CustomSerializable may not be used in un-typed collections, such as ArrayLists.
通过动态生成的 XML 程序集,我们最终通过调用返回到 .NET 标准库代码:
System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(
String, String, Object, Boolean) : Void
反过来,这会导致:
protected Exception CreateUnknownTypeException(Type type)
{
if (typeof(IXmlSerializable).IsAssignableFrom(type))
{
return new InvalidOperationException(
Res.GetString("XmlInvalidSerializable",
new object[] { type.FullName }));
}
// Rest omitted...
Reflector 显示 XmlInvalidSerializable
资源对应于上面的字符串——即,WriteTypedPrimitive
不喜欢 IXmlSerializable
。
如果我们生成一个非多态的序列化器,像这样:
XmlSerializer xs = new XmlSerializer(typeof(CustomSerializable));
.NET 将生成对以下内容的调用:
System.Xml.Serialization.XmlSerializationWriter.WriteSerializable(
IXmlSerializable, String, String, Boolean) : Void
这会正确处理 IXmlSerializable
。有人知道为什么 .NET 在多态情况下不使用这个函数吗?查看 XML 序列化程序生成的 C#,在我看来这可以很容易地完成。这是我从 XML 序列化程序中获得的一些代码,其中包含一个未经测试的解决方案:
void Write1_Object(string n, string ns, global::System.Object o,
bool isNullable, bool needType)
{
if ((object)o == null)
{
if (isNullable) WriteNullTagLiteral(n, ns);
return;
}
if (!needType)
{
System.Type t = o.GetType();
if (t == typeof(global::System.Object))
{
}
>>> patch begin <<<
+ else if (typeof(IXmlSerializable).IsAssignableFrom(t))
+ {
+ WriteSerializable((System.Xml.Serialization.IXmlSerializable)
((global::CsFoo.CustomSerializable)o),
+ @"CustomSerializable", @"", true, true);
+ }
>>> patch end <<<
else
{
WriteTypedPrimitive(n, ns, o, true);
return;
}
}
WriteStartElement(n, ns, o, false, null);
WriteEndElement(o);
}
这是否出于技术原因或仅仅是功能限制而被遗漏?不支持的功能,还是我的白痴?我的 intertubes Google 技能让我失望了。
我确实在这里找到了一些相关问题,其中“C# Xml-Serializing a derived class using IXmlSerializable”最相关。这让我相信这是不可能的。
在那种情况下,我目前的想法是在根基类中注入(inject)默认的 IXmlSerializable
实现。然后一切都将是一个 IXmlSerializable
,并且 .NET 不会提示。我可以使用 Reflection.Emit 为每个具体类型生成 ReadXml
和 WriteXml
主体,生成的 XML 看起来与我使用库一时一样。
有些人在遇到 XML 序列化问题时会想“我知道,我会使用 Reflection.Emit 来生成代码”。现在他们有两个问题。
附言笔记;我知道 .NET 的 XML 序列化的替代方案,并且知道它有局限性。我还知道保存 POCO 比处理抽象数据类型要简单得多。但是我有一堆遗留代码,需要对现有 XML 模式的支持。
因此,虽然我很欣赏显示这在 SomeOtherXML
、YAML
、XAML
、ProtocolBuffers
中有多么容易的回复、DataContract
、RandomJsonLibrary
、Thrift
或您的 MorseCodeBasedSerializeToMp3
库 - 嘿,我可能会学到一些东西 -,我什么我希望有一个 XML 序列化程序解决方案,如果不是解决方案的话。
最佳答案
当使用 object
时,我能够重现您的问题:
XmlSerializer xs = new XmlSerializer(
typeof(object),
new Type[] { typeof(CustomSerializable) });
但是,我随后创建了 CustomSerializable
的派生类:
public class CustomSerializableDerived : CustomSerializable
{
}
并尝试序列化它:
XmlSerializer xs = new XmlSerializer(
typeof(CustomSerializable),
new Type[] { typeof(CustomSerializableDerived) });
这有效。
因此,问题似乎仅限于您将“对象”指定为要序列化的类型的情况,但如果您指定具体的基类型则不会。
我会在早上对此进行更多研究。
关于c# - 多态类型和 IXmlSerializable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/631852/
我需要能够对内部类进行 Xml 序列化,因此我必须实现 IXmlSerializable。 这个类有两个字符串和一个列表。 我知道使用 WriteElementString 和 ReadElement
我有一个看起来像这样的 xml 文件: value value value value 我有两个对象代表这个 xml: class
.NET 中的 XML 序列化通过 XmlSerializer 构造函数的 extraTypes[] 参数允许多态对象。它还允许为实现 IXmlSerializable 的类型自定义 XML 序列化。
我正在实现 IXmlSerializable对于我的类的自定义(反)序列化逻辑,但希望根据 XSD 模式检查 XML 的读写。我添加了 XmlSchemaProviderAttribute : [Xm
假设我有两个类,一个基类和一个派生类。它们是相当简单的类,主要充当数据结构(派生类显然稍微复杂一些)。 public class BaseUserSession { // ... Variou
我试图创建一个通用的 Dictionary实现 IXmlSerializable (归功于 Charles Feduke )。 这是我的试验: Sub Main() Dim z As New
我正在构建一个将数据公开为 XML 的 REST API。我的域层中有一大堆域类,供 API 后面的服务层和我们将提供给客户的客户端 API 使用。 (客户确实可以选择直接与 REST API 交互,
是否有任何标记为 IXmlSerializable 的 .NET 通用集合?我已经尝试过 List 和 Collection,但都没有开箱即用。 在我推出自己的 collection、list 或 d
我对 xml 序列化有一个奇怪的要求。 请引用以下 C# 代码(由于变量 'rootName' 超出范围而无法编译)。我的意图是让我的类(class) GeneralData 成为“一般”。这意味着该
我有一个类: [Serializable] public class Profile { [XmlAttribute] private string[] permissions;
我想对我的对象 Exception 的实例进行 XML 序列化,并将其存储在另一个对象 ExceptionReport 的 XMLNode[] Nodes 属性中。 [System.Diagnosti
我有一个实现 IXmlSerializable 的类,如下所示: public class SomeClass : IXmlSerializable { public SomeSerializ
一旦程序员决定实现IXmlSerializable,实现它的规则和最佳实践是什么?我听说 GetSchema() 应该返回 null 并且 ReadXml 应该在返回之前移动到下一个元素。这是真的?那
我有这样的 xml: 2 6,501698000000 8,414278000000 9,29
对于要使用的正确装饰器或可能需要的任何设计有点困惑。当序列化一个实现 IXmlSerializable 的类时,有没有办法在 XmlRoot 元素中包含命名空间及其前缀? 例如类定义。 using S
我有以下类定义 [XmlRoot(ElementName = "person",Namespace = "MyNamespace")] public class Person : IXmlSerial
我有一个自定义类型的集合属性,它继承自 BindingList。目前,此属性通过 XmlSerializer 进行序列化,即使它没有 Setter。我现在正尝试在此自定义集合类上实现 IXmlSeri
初始问题 我要serialize一个List更改 IXmlSerializable 的 XmlType动态分类(所以我不能使用属性标签来做到这一点) 我已经尝试使用 XmlAttributeOverr
我发现 XmlSerializer 有一些有趣的行为。 如果我尝试序列化一个具有 Type 对象属性并且该对象实现了 IXmlSerializable 的类,序列化程序将抛出一个 InvalidOpe
基本上,最初的问题是我需要将 bool 值序列化为 0 或 1。我找到的解决方案是实现 IXmlSerializable,我确实这样做了。不幸的是,我试图序列化的类是从模式生成的代码,并且上面有一个
我是一名优秀的程序员,十分优秀!