9

同时针对 2.0、3.0、3.5、4.0 和 4.5 的单个 .NET 程序集如何支持 C# 和 VB.NET 使用者的扩展方法?

标准建议是添加以下内容:

namespace System.Runtime.CompilerServices
{
  public sealed class ExtensionAttribute : Attribute { }
}

这种方法由不止一位 Microsoft 员工建议,甚至MSDN杂志中出现。它被许多博主广泛称赞为“没有不良影响”。

哦,除了它会导致针对 .NET 3.5 或更高版本的 VB.NET 项目的编译器错误。

Microsoft.Core.Scripting.dll 的作者想通了,并将“公共”更改为“内部”。

namespace System.Runtime.CompilerServices
{
  internal sealed class ExtensionAttribute : Attribute { }
}

这似乎解决了VB兼容性问题。

因此,我信任地将这种方法用于广泛使用的 ImageResizing.Net 库的最新版本(3.2.1) 。

但是,对于某些针对 .NET 3.5+ 的用户,我们开始或多或少随机地收到此编译器错误(原始报告)。

Error 5 Missing compiler required member
'System.Runtime.CompilerServices.ExtensionAttribute..ctor'

因为 MSBuild/VisualStudio 编译器在解决命名冲突时显然不会费心查看范围规则,并且程序集引用的顺序扮演的角色并不完全记录,所以我不完全理解为什么以及何时发生这种情况。

一些 hacky 解决方法,例如更改程序集命名空间、重新创建项目文件、删除/读取 System.Core,以及调整 .NET 框架的目标版本。不幸的是,这些变通方法都不是 100%(除了混叠,但这是一个不可接受的痛苦)。

我该如何解决这个问题

  1. 维护对在程序集中使用扩展方法的支持,
  2. 维护对 .NET 2.0/3.0 的支持
  3. 每个 .NET 框架版本不需要多个程序集。

或者,是否有让编译器注意范围规则的修补程序?

未回答此问题的关于 SO 的相关问题

4

1 回答 1

2

我们在 IronPython 上遇到了同样的问题。http://devhawk.net/2008/10/21/the-fifth-assembly/

我们最终将自定义版本的 ExtensionAttribute 移动到它自己的程序集中。这样,客户可以在引用我们的自定义 ExtensionAttribute 程序集或 System.Core 之间进行选择——但不能同时引用两者!

另一个棘手的问题是您必须始终部署 E​​xtensionAttribute 程序集——即使您没有在项目中引用它。公开扩展方法的项目程序集将具有该自定义 ExtensionAttribute 程序集的 assemblyref,因此如果找不到它,CLR 会感到不安。

鉴于.NET 2.0 支持的硬性要求,我认为最好的选择是根本不使用扩展方法。我不熟悉 ImageResizer 项目,但听起来这是 ImageResizer 的最新变化。将扩展方法更改为传统的静态方法有多可行?实际上,我们曾为 IronPython/DLR 考虑过这一点,但这并不可行(当时我们与 LINQ 合并,而 LINQ 基本上在其整个存在过程中都大量使用了扩展方法)。

于 2012-06-20T05:13:34.950 回答