为自定义XmlSerializer生成Xml序列化程序集

我的类中有方法使用与使用默认序列化程序生成的XML结构不同的XML结构进行序列化/反序列化。 这些方法为我的类型创建了一个XmlSerializer,但是有一大堆覆盖。 当调用这些方法时,我猜.NET内部仍会生成序列化程序集,但我想在编译后生成此程序集,因此它不会在运行时生成。 如何为此自定义序列化生成序列化程序集? 如果我对该类型使用sgen.exe,它似乎只生成默认的序列化程序。

特别是我需要生成序列化程序集的原因是我的代码是从Internet Explorer进程中调用的,它在保护模式下运行。 如果.net运行时尝试生成序列化程序集,则会调用csc.exe并提示用户,询问是否允许运行此进程。 我不希望提示用户! 所以需要在没有csc.exe的情况下完成所有序列化/反序列化。

我能想到的一个选择是捕获在运行时生成的.cs,将它放在一个单独的程序集中,然后将其包含在我的产品中。 除了有点icky,这引发了如何自动生成.cs作为我的构建过程的一部分的问题…

也许值得一提的是:我的自定义xml序列化也序列化了嵌套类,因此也许会有自动生成的序列化器。 我的自定义序列化主要是按照以下几行完成的 – 它将XmlIgnore添加到某些属性中,并从其他属性中删除XmlIgnore。 其中许多属性返回需要序列化的对象,其中一些实现IXmlSerializable,一些使用默认序列化。

public void SerializeToCustomXml1(XmlWriter writer) { try { CustomXmlSerializer1.Serialize(writer, this); } catch (Exception) { } } ///  /// Static serializer so it's created just once. There's another one like this CustomXmlSerializer2 with a slightly different format again. ///  private static XmlSerializer CustomXmlSerializer1 { get { if (_customXmlSerializer == null) { XmlAttributes dontIgnore = new XmlAttributes(); dontIgnore.XmlIgnore = false; XmlAttributes attributes; XmlAttributeOverrides overrides = new XmlAttributeOverrides(); // Include some fields in the XML that wouldn't be there otherwise. overrides.Add(typeof (WebResource), "ID", dontIgnore); overrides.Add(typeof (WebResource), "HasDestinationURLs", dontIgnore); overrides.Add(typeof (Resource), "AccessDefindBy", dontIgnore); attributes = new XmlAttributes(); attributes.XmlIgnore = false; attributes.XmlElements.Add(new XmlElementAttribute("ActionID")); overrides.Add(typeof(Action), "ID", attributes); // Instead of serializing the Actions field we serialize CustomActionsXmlSerializer, // which outputs different content in the XML overrides.Add(typeof (WebResource), "Actions", ignore); attributes = new XmlAttributes(); attributes.XmlIgnore = false; attributes.XmlElements.Add(new XmlElementAttribute("Actions")); overrides.Add(typeof (WebResource), "CustomActionsXmlSerializer", attributes); // ... more of these overrides here ... _customXmlSerializer1 = new XmlSerializer(typeof(WebResource), overrides); } return _customXmlSerializer1; } 

在这里和这里交叉发布。

更新:哦, 这个答案表明它是不可能的,因为如果你使用XmlOverrides,XmlSerializer甚至不会寻找预编译的程序集。 该死。 然后我想我最好的选择是生成序列化代码并将其包含在我的项目中并直接调用它而不是调用XmlSerializer。 关于如何做到这一点的任何想法?

如果您使用“自定义XmlSerializer”意味着您使用System.Xml.XmlSerializer与自定义序列化代码(通过IXmlSerializable[XmlElement]属性和朋友),它应该在序列化时查找名为MyAssembly.XmlSerializers.dll的程序集。

程序集的命名很重要,如果你不确定它是否正在查找以及正在查找的程序集名称,你可以将一个事件处理程序附加到AppDomain.CurrentDomain.FirstChanceException ,它将触发所有exception。应用程序域,包括程序集加载exception。 您还可以挂钩到AppDomain.CurrentDomain.AssemblyLoadAppDomain.CurrentDomain.AssemblyResolve事件,每次首次将程序集加载到应用程序域时都会触发这些事件。

另一个重要的事情是MyAssembly.dllMyAssembly.XmlSerializers.dll的版本(也许是密钥;我不确定)必须匹配,它们也应该放在一起。 有关详细信息,请参阅此 MSDN文章 。

(还没有足够的评论点)

您应该考虑咬住子弹并以允许您决定序列化和不序列的方式实现IXmlSerializable,而无需在运行时更改属性。 定义自己的属性,构造函数要求并对其进行序列化。

也许你甚至可以解雇XML-Serialization并切换到JSon.Net,在那里需要跳过这样的环节是不太可能的。