使用 XmlSerializer 时如何向 XML 文件写入注释?

2024-06-22

我有一个对象 Foo,我将其序列化为 XML 流。

public class Foo {
  // The application version, NOT the file version!
  public string Version {get;set;}
  public string Name {get;set;}
}

Foo foo = new Foo { Version = "1.0", Name = "Bar" };
XmlSerializer xmlSerializer = new XmlSerializer(foo.GetType());

它工作起来快速、简单,并且可以完成当前所需的一切。

我遇到的问题是我需要维护一个单独的文档文件,其中包含一些小注释。正如上面的例子,Name是显而易见的,但是Version是应用程序版本,而不是本例中所期望的数据文件版本。我还有很多类似的小事情想通过评论来澄清。

我知道如果我使用以下命令手动创建 XML 文件就可以做到这一点WriteComment()函数,但是我是否可以实现一个可能的属性或替代语法,以便我可以继续使用序列化器功能?


通过使用返回类型对象的属性,可以使用默认基础结构来实现这一点XmlComment https://msdn.microsoft.com/en-us/library/system.xml.xmlcomment.aspx并将这些属性标记为[XmlAnyElement("SomeUniquePropertyName")] https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlanyelementattribute.aspx.

IE。如果您添加一个属性Foo像这样:

public class Foo
{
    [XmlAnyElement("VersionComment")]
    public XmlComment VersionComment { get { return new XmlDocument().CreateComment("The application version, NOT the file version!"); } set { } }

    public string Version { get; set; }
    public string Name { get; set; }
}

将生成以下 XML:

<Foo>
  <!--The application version, NOT the file version!-->
  <Version>1.0</Version>
  <Name>Bar</Name>
</Foo>

然而,问题所要求的不仅仅是这个,即某种在文档系统中查找评论的方法。以下通过使用扩展方法根据反映的注释属性名称查找文档来实现此目的:

public class Foo
{
    [XmlAnyElement("VersionXmlComment")]
    public XmlComment VersionXmlComment { get { return GetType().GetXmlComment(); } set { } }

    [XmlComment("The application version, NOT the file version!")]
    public string Version { get; set; }

    [XmlAnyElement("NameXmlComment")]
    public XmlComment NameXmlComment { get { return GetType().GetXmlComment(); } set { } }

    [XmlComment("The application name, NOT the file name!")]
    public string Name { get; set; }
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class XmlCommentAttribute : Attribute
{
    public XmlCommentAttribute(string value)
    {
        this.Value = value;
    }

    public string Value { get; set; }
}

public static class XmlCommentExtensions
{
    const string XmlCommentPropertyPostfix = "XmlComment";

    static XmlCommentAttribute GetXmlCommentAttribute(this Type type, string memberName)
    {
        var member = type.GetProperty(memberName);
        if (member == null)
            return null;
        var attr = member.GetCustomAttribute<XmlCommentAttribute>();
        return attr;
    }

    public static XmlComment GetXmlComment(this Type type, [CallerMemberName] string memberName = "")
    {
        var attr = GetXmlCommentAttribute(type, memberName);
        if (attr == null)
        {
            if (memberName.EndsWith(XmlCommentPropertyPostfix))
                attr = GetXmlCommentAttribute(type, memberName.Substring(0, memberName.Length - XmlCommentPropertyPostfix.Length));
        }
        if (attr == null || string.IsNullOrEmpty(attr.Value))
            return null;
        return new XmlDocument().CreateComment(attr.Value);
    }
}

为此生成以下 XML:

<Foo>
  <!--The application version, NOT the file version!-->
  <Version>1.0</Version>
  <!--The application name, NOT the file name!-->
  <Name>Bar</Name>
</Foo>

Notes:

  • 扩展方法XmlCommentExtensions.GetXmlCommentAttribute(this Type type, string memberName)假设评论属性将被命名xxxXmlComment where xxx是“真实”的财产。如果是这样,它可以通过标记传入的内容来自动确定真实的属性名称memberName属性与CallerMemberNameAttribute https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx。可以通过传入真实姓名来手动覆盖此设置。

  • 一旦知道类型和成员名称,扩展方法就会通过搜索[XmlComment]应用于属性的属性。这可以替换为对单独文档文件的缓存查找。

  • 虽然仍然需要添加xxxXmlComment每个可能被注释的属性的属性,这可能比实施IXmlSerializable直接地 https://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly这是相当棘手的,可能会导致反序列化中的错误,并且可能需要复杂子属性的嵌套序列化。

  • 要确保每个注释位于其关联元素之前,请参阅控制 C# 中的序列化顺序 https://stackoverflow.com/q/3373529.

  • For XmlSerializer要序列化属性,它必须同时具有 getter 和 setter。因此,我给出了不执行任何操作的注释属性设置器。

Working .Net小提琴 https://dotnetfiddle.net/yjI8Z6.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 XmlSerializer 时如何向 XML 文件写入注释? 的相关文章

  • 如何将 CroppedBitmap 转换为 BitmapImage

    我正在尝试将 CroppedBitmap 转换为 BitmapImage 编辑 不使用内存流 我尝试过直接转换它 似乎这不是一个选择 这应该没那么难 我正在尝试剪切 BitmapImage 的一部分 并创建一个仅包含新裁剪的 Bitmap
  • C# Visual Studio 动态代码片段

    我正在开发一个 WinForms 项目 每天都会执行一些重复性的任务 所以我认为创建代码片段 https msdn microsoft com en us library ms165394 v vs 110 aspx会帮助我 但它仅适用于固
  • 将标准库添加到C++ eclipse项目中

    一个 非常 新手 C 问题 有没有办法自动将标准库添加到 C eclipse 项目中 我安装了 CDT 主要功能插件 您可以手动添加 STL 标头的路径路径和符号 gt 包含选项卡 http help eclipse org galileo
  • 命令中带空格的 Windows C 系统调用

    我无法使用名称和参数中的空格进行系统调用 例如 system c program files something example exe c my files example txt 我尝试过各种我知道的方法来逃避 但没有任何效果 我努力了
  • 用于 C/C++ 的独立跨平台 (Windows/Linux) 文件压缩?

    我正在寻找一个 最好是小的 C 或 C 开源库 我可以将其包含在我的 MIT 许可项目中 托管在 google 代码上 我是一名业余爱好 C C 程序员 所以我并不那么先进 但我只知道为名为 SA MP 的应用程序 适用于 Windows
  • 如果 .txt 文件不存在,则创建一个,如果存在则追加新行

    我想创建一个 txt 文件并写入它 如果该文件已经存在 我只想添加更多行 string path E AppServ Example txt if File Exists path File Create path TextWriter t
  • 测试从 ComboBox 派生的自定义控件

    我创建了一个从 ComboBox 派生的控件 并希望对其行为进行单元测试 但是 它在我的单元测试中的行为似乎与实际应用程序中的行为不同 在实际应用程序中 Combobox DataSource 属性和 Items 同步 换句话说 当我更改
  • argc 和 argv 在 Windows 中没有用吗?

    在 Linux 中 argc 和 argv 计算终端中的参数 但在 Windows 中 我找不到放置第二个参数的地方 事实上 每次我运行该程序时 它都会创建那个丑陋的黑色窗口 我什至没有机会给出任何争论 那么这两个变量在Windows平台下
  • 实体框架中的导航属性是什么

    我是实体框架的新手 当Visual Studio创建模型图时我们主要可以看到Entities Propertie和Navigation Properties这两个东西 那么这些Navigation Properties是什么 如何使用它们
  • 简单的喷射器将具体类型与生活方式结合起来

    我正在寻找一种可以使用指定的生活方式注册具体类型的方法 基本上如下所示 public void SomeFunction Type concrete Lifestyle lifestyle gt container Register con
  • 防止单个可执行文件的多个进程实例

    我正在使用 NET 和 C 我想阻止同一可执行文件的两个实例同时运行 但我不想阻止从另一个文件夹运行的同一进程 例如 我有一个位于两个不同位置的可执行文件 C MyProject Master Program exe C MyProject
  • 在 C# 中为 ListBox 分配数据源时,如何从 ListBox 中删除所选项目?

    在 C 中为 ListBox 分配数据源时 如何从 ListBox 中删除所选项目 尝试删除时出现错误 设置 DataSource 属性后 无法修改项目集合 但是当我尝试从数据源 数据表 中删除项目时 它会抛出错误 因为 数据行不在当前行集
  • Task.Delay 到底是如何工作的?

    他们说 Task Delay 是一个异步 Thread Sleep 为了测试这一点 我写了下面的代码 我希望立即打印 One 然后 3 秒后将打印结果变量 15 2 秒后 将打印 Two 但似乎并非如此 一 不会立即打印 3 秒后打印 On
  • 64 位随机生成器种子

    我目前正在运行一个具有 8 个以上管道 线程 的多线程模拟应用程序 这些管道运行非常复杂的代码 该代码取决于种子生成的随机序列 然后该序列被归结为单个 0 1 我希望在将种子从主线程传递到处理管道后 这种 随机处理 具有 100 的确定性
  • 预览MouseMove 与 MouseMove

    我有相当多的 XAML 经验 但最近我注意到我的大多数同事都使用预览鼠标移动代替鼠标移动事件 我一直用鼠标移动它对我很有帮助 但我忍不住问我什么时候应该使用预览鼠标移动什么时候鼠标移动 有什么区别 各自有什么优点和缺点等等 PreviewM
  • 具有可导出私钥的证书的“错误密钥”例外

    我正在尝试使用非对称加密来加密然后解密文件 我已经使用 makecert 创建了一个测试证书并将其安装到我的个人本地计算机存储中 将来我必须在多个服务器上安装此证书 这就是为什么我使用 pe 标志创建它 即使用可导出的私钥 证书已成功创建并
  • 如何以一对一/零关系更新员工和身份用户

    我正在尝试更新员工记录 也想更新身份用户 如果我先单独更新身份用户 例如 UserManager Update user Context Entry employee State System Data Entity EntityState
  • 从不同的线程访问对象

    我有一个服务器类 它基本上等待来自客户端的连接 在该类中 我创建了一个 NetworkStream 对象 以便能够从客户端接收字节 由于 NetworkStream Read 方法不是异步的 这意味着它将等到从客户端读取字节才能继续执行类似
  • RC4 实现与 openssl 输出不匹配

    我的目标是在 C C 中实现 RC4 流密码 并确保它产生与使用时相同的输出openssl命令 按照伪代码维基百科 https en wikipedia org wiki RC4 该实现似乎有效 因为它可以加密和解密内容 但是 加密的输出与
  • simplexml,返回具有相同标签的多个项目

    我将以下 XML 文件加载到 php simplexml 中

随机推荐

  • ArangoDB 读取超时(读取超时=60)

    我有个问题 我在用ArangoDB enterprise 3 8 6 via Docker 但不幸的是我的查询花费的时间比30s 当失败时 错误是arangodb HTTPConnectionPool host 127 0 0 1 port
  • 使用 iText 在 PDF 表格中添加一行

    我在这段代码中得到的是一个 8 列 3 行的表格 我应该怎么做才能只得到 2 行 3 行中的第一列是空的 但其余单元格填充有 hi Code PdfPTable table new PdfPTable 8 PdfPCell cell cel
  • Google 表格 - 提取数字及其测量单位

    我想要一个可以从文本中提取数字及其测量单位的函数 例如在 A2 中我有 这个盒子重5公斤 另一个盒子重10公斤 所以我想要一个会返回的函数 5kg 10kg 注意 我希望该函数适用于任何测量单位 而不仅仅是 kg 我是谷歌表格的初学者 因此
  • DW_AT_location的用途和含义

    我想知道如何使用属性 DW AT location 进行调试 它是 dwarf 为调试指定的属性之一 但无法真正理解它到底代表什么 当我们编译代码时 什么时候应该发出这个属性 来自 DWARF 3 规范 http dwarfstd org
  • 我如何获得 Windows 版 libmemcached?

    我正在尝试在我的 Windows 本地主机中安装 memcached 扩展 wamp 64 php 5 5 12 请参阅 memcached https pecl php net package memcached https pecl p
  • 将文本转换为 Varchar

    In Postgresql如何将文本字段转换为 varchar 我已经尝试了以下两种方法 但都没有将我的文本字段转换为 varchar Cast Iamtextfield As Varchar Char Iamtextfield text
  • 为什么 CompletableFuture.supplyAsync 会成功随机次数?

    我对 Java 8 中的 lambda 表达式和异步代码都很陌生 我不断得到一些奇怪的结果 我有以下代码 import java util concurrent CompletableFuture public class Program
  • 如何向导航控制器添加按钮

    这是我的代码 我无法在导航控制器中添加按钮 BOOL application UIApplication application didFinishLaunchingWithOptions NSDictionary launchOption
  • Spring注入绑定到Instance

    有没有一种方法可以使用类似于 Google Guice 的 Spring DI 将注入的对象绑定到特定实例 bind MyClass class toInstance myclassobject 如果构造函数或成员变量被注释为 Autowi
  • 将两个 laravel AJAX 函数合并到一条路径中

    我正在尝试将数据插入数据库 并且我的两个功能都可以工作 但是当我尝试缩短它并放入一些常见内容时 它就无法工作 我认为问题出在我的第一个函数中 我正在使用图像 并且对于该 contentType 所有细节都不同 这就是它不起作用的原因 这是我
  • 是否可以在 ECB 模式下将 AES 与 IV 结合使用?

    From http php net manual en function mcrypt encrypt php http php net manual en function mcrypt encrypt php 我看到以下代码在 ECB
  • 哪个 NuGet 包会在 Views 文件夹中创建 web.config?

    我的项目缺少web config文件来自Views文件夹 以下是我制作该项目所采取的步骤 创建一个空的 MVC 项目并安装下面列出的包 创建了控制器和视图 该视图是通过右键单击操作名称并从菜单中选择 添加视图 来创建的 尝试运行项目 但出现
  • 在 System Verilog 中检测时间刻度

    如何从源代码中检测模拟中使用的时间刻度精度 考虑我有一个配置参数 cfg delay i 其中用户以时间单位给出了一些延迟值 如下所示fs 如果用户给出1000 我的代码必须等待1000fs 或 1ps在进一步执行之前 cfg delay
  • JMS点对点聊天

    我正在尝试进行简单的点对点聊天 但运行程序后出现异常 javax naming CommunicationException Failed to get registry service for URL tcp localhost 8080
  • jQuery 验证插件:valid() 不适用于远程验证?

    我开始关注这个很棒的教程 http sleekd com tutorials jquery validation in ruby on rails 但想在 keyup 上进行验证并将我的错误放在其他地方 远程验证在适当的时间显示自己的错误消
  • 如何在Python中小写列表[重复]

    这个问题在这里已经有答案了 我正在尝试读取 jupyter 笔记本中的文本文件并获取文件中的唯一单词 我将该文件作为列表读取 然后尝试对其应用小写 但是 lower 函数不适用于列表 请帮忙做同样的事情 使用 val 中的值列表 您可以执行
  • 嵌套循环中数组的二维累积和——CUDA实现?

    我一直在考虑如何使用归约在 CUDA 上执行此操作 但我对如何完成它有点不知所措 C 代码如下 要记住的重要部分 变量预先计算的值依赖于取决于both循环迭代器 另外 变量ngo并不是每个值都是唯一的m 例如m 0 1 2 可能有ngo 1
  • 如何翻转vim中视觉选择的线条?

    我想进行视觉选择并将其翻转 以便选择的第一行位于底部 从
  • 连接字符串而不是使用一堆 TextBlock

    我想在 WPF ItemsControl 中显示 Customer 对象的列表 我为此创建了一个数据模板
  • 使用 XmlSerializer 时如何向 XML 文件写入注释?

    我有一个对象 Foo 我将其序列化为 XML 流 public class Foo The application version NOT the file version public string Version get set pub