我可以使用 .NET 属性而不依赖于定义它的程序集吗?

Can I use a .NET attribute without depending on the assembly that defines it?

我不清楚有关属性和程序集依赖项的规则。

是否有可能(并且不是一个糟糕的想法)使用 NuGet 包中的自定义属性注释程序集中的类型 引入 运行 时间依赖性在那个 NuGet 包上?客户是否可以使用程序集中的类型而不需要自定义程序包的程序集?

我问是因为我的 .NET 应用程序使用了两个包:

  1. 名为 YamlDotNet 的第三方 NuGet 包,用于将类型序列化为 YAML。它允许您使用类似于 Microsoft 的 XML 属性的自定义属性来控制 YAML 序列化(例如,它具有 YamlIgnoreAttribute,就像 MS 的 XmlIgnoreAttribute

  2. 我自己的包,PackageA 依赖于 YamlDotNet。

我希望我的应用使用 YamlDotNet 从 PackageA 序列化我的类型。但除非我执行以下操作之一,否则它们将无法正确序列化:

  1. 使用 YamlDotNet 自定义属性注释 PackageA 中的类型
  2. 为应用程序中的 PackageA 类型创建带注释的包装器,以便为我进行序列化。

我可以做#2,但做#1 会更容易。但我不想为 PackageA 的所有客户端引入对 YamlDotNet 的 运行 时间依赖。 理想情况下,我希望任何使用 PackageA 且碰巧也在使用 YamlDotNet 的人都可以免费获得这些属性,并且其他任何人都看不到它们。

我想要的有可能吗?

属性是一个 compile-time 特性,您将始终需要参考 YamlDotNet 以便将其中一种类型用作 compile-time 类型元数据,除非您愿意做诸如生成模型之类的事情类 in run-time(这很可能比有一个额外的包参考更麻烦)。

这是一个普遍问题,使用序列化程序的 attribute-driven 功能会污染目标程序集并将其与序列化程序耦合。

可以通过三种方式解决这个问题:

  1. 接受这个作为妥协
  2. 将 YamlDotNet-specific 移动到单独的程序集中
  3. 有单独的序列化模型

第一点应该很清楚——这是你不想要的,也是你的第一个建议。

第二点可能是在单独的程序集中创建 YamlDotNet-specific 类型包装器或类型转换器(如果它支持此类东西),以便核心程序集保持清洁。这是你的第二个建议,只是带有转换器的扭曲,这可能比从消费者的角度包装所有东西更令人愉快。

第三点是关于在核心程序集中创建 DTOs/payloads,这样您就不必使用任何 serializer-specific 属性,并且序列化开箱即用。如果您需要 [YamlIgnore] 属性,用于序列化的模型可能还用于其他目的,因此这基本上只是关注点分离。如果序列化应用程序模型,您可能会发现无法在不影响各个地方的业务逻辑的情况下提供向后兼容性。