针对 .NET 框架的多个版本的最佳方法是啥?
Posted
技术标签:
【中文标题】针对 .NET 框架的多个版本的最佳方法是啥?【英文标题】:What's the best way to target multiple versions of the .NET framework?针对 .NET 框架的多个版本的最佳方法是什么? 【发布时间】:2013-07-16 00:34:22 【问题描述】:我正在构建一个类库,并将其部署为 NuGet 包,它允许我根据添加到的项目的 .NET 框架版本选择不同的程序集作为引用添加。这是一个非常好的功能,但我想知道是否可以拥有一个类库项目,并针对多个版本的 .NET 框架构建它?
我宁愿避免:
MyLibrary40.dll
和 MyLibrary45.dll
如果可能的话,因为这两个项目将不得不共享大量代码。 4.5 版本将提供 async
函数,这是 4.5 的功能。
有谁知道最好的方法是什么?我可以使用多个构建配置吗?还是我必须走单独的项目路线?
如果我在 C++ 中工作,我可能会使用多个配置和 #if
块围绕仅在一种配置中受支持的功能,但我担心这会导致我有两个同名但做不同的程序集东西。
提前致谢!
【问题讨论】:
所以你想在一个程序集中定位不同的版本? 这是获得 BadImageException 的最佳方法 :) 但是,我找到了一个可以编译的解决方法,您可以查看我在问题中提供的链接,它们可能会对您的旅程有所帮助 - ***.com/questions/15549011/… @LarsKristensen,我想要一个项目文件,但能够生成两个程序集——一个支持 .NET 4.0,一个支持 .NET 4.5 并添加一些异步功能——无需创建单独的项目.. 我也问过这个,没有给出严格的答案,也许你会有比我更好的答案,你需要的是配置管理器..***.com/questions/15321757/… 【参考方案1】:如果是现在,您可以创建“SDK 样式项目”。 MSDN
【讨论】:
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:我知道的老问题,当时这不是一个合适的答案......但现在可以使用共享项目,这在逻辑上与将项目添加为链接而不是单独添加每个文件相同。
【讨论】:
好主意,但它有很多限制,最明显的是你的类库不能引用任何不是共享项目的东西。我想这是有道理的,但在每个 NuGet 包都是共享项目之前,在大多数情况下可能没有用。 嗯,不知道你在这里指的是什么。我可以创建一个共享库 A 和一个引用 A 和 Newtonsoft NuGet 包的类库 B。然后我可以在 A 中编写代码,使用例如对象。在 VS2015 和 VS2017 中都是如此【参考方案3】:一个简单的方法是在同一文件夹中添加另一个.csproj
文件,并将其配置为构建不同的框架版本。这避免了必须添加文件链接,因为这两个项目本质上都是视图在同一个文件夹结构上。
假设你有结构:
- MyLibrary\
- MyLibrary.sln
- MyLibrary\
- MyLibrary.csproj
- Program.cs
将MyLibrary.csproj
复制到同一文件夹并进行编辑以更改一些内容:
<ProjectGuid>
只需为此元素的值创建一个新的 GUID
<TargetFrameworkVersion>
在此处指定替代版本,例如:v4.5
或 v3.5
<OutputPath>
(用于调试和发布)将此设置为唯一路径,例如 bin\Debug\net45
和 bin\Debug\net45
,以允许每个项目的输出最终位于唯一位置
您还必须向非条件<PropertyGroup>
元素添加一个新元素,以使两个项目在并行构建期间不会在obj
文件夹中发生冲突。这很重要,可以防止出现奇怪的竞争条件错误。
<PropertyGroup>
<BaseIntermediateOutputPath>obj\net45\</BaseIntermediateOutputPath>
最后,将这个新项目添加到您现有的解决方案中。
此方法与定义编译开关(例如 NET35
和 NET45
)以及使用 #if NET35
/ #endif
指令密切相关。
使用这种技术的两个开源项目是MetadataExtractor 和NetMQ。您可以参考他们以防万一。
【讨论】:
如果您使用 Visual Studio 2015,@DrewNoakes 的答案是否仍然可行?还是现在有更好的方法来做到这一点?只是想知道 我在 Visual Studio 2015 中使用它。但是一旦 xproj/project.json 东西落地,这可能是针对多个平台的更好方法。 感谢您的快速回答...我会记住这一点的。 @O.R.Mapper,是的,它并不完美。如果幸运的话,一个项目将无法构建。否则你可能会错过一个文件。然而,在某些情况下,您需要——也许您为某个目标版本中缺少的东西提供了一个 shim 类。如果您知道更好的解决方案,我会全力以赴。 @O.R.Mapper 如果您使用已接受的答案添加任何文件,您仍然必须记住将它们链接到任何其他项目中。【参考方案4】:您至少需要一个带有 2 个项目的 VisualStudio 解决方案(一个用于 .net 4,一个用于 .net 4.5)。
将所有代码文件添加到 .net 4 项目中,然后在另一个项目中添加代码文件作为链接(使用 "Add Existing Item..."
-Dialog 并选择 Add as link
)
现在您将 .NET 4.5 的所有代码和类添加到您的 4.5 项目中。
此外,您应该为您的项目定义自己的编译器开关(条件编译符号)。就像 NET4 用于您的 .net 4 项目和 NET4.5 用于您的 .net 4.5 项目)
您在 Build->General->Conditional Compilation Switches 下的项目设置中设置开关
在您的代码中,您可以使用如下开关为 .NET 4 或 .NET 4.5 生成代码
#if NET4
// code only for .NET 4
#endif
// code for all framework versions.
#if NET45
// code only for .NET 4.5
#endif
【讨论】:
非常感谢,这确实是我走的路。我有一个名为“JsonClient”的 .NET Framework 4.5 类库,它具有所有功能。 .NET 4.0 版本称为“JsonClientLite”,包含完全相同的代码,但我没有使用条件编译,而是为每个具有异步方法的类创建了一个单独的文件(所以我在这两个文件中都有 JsonClient.cs,仅在主要的) - 我使用.NET 4.0中的文件的快捷方式,就像你描述的那样。我对它的工作原理很满意,这似乎是一条干净的路 - 非常感谢您的回答! 我写了 github.com/CADbloke/CodeLinker 来解决这个问题 - 它使用现有项目中的项目填充新项目。以上是关于针对 .NET 框架的多个版本的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
使用 XCode 将同一 iOS 应用程序的多个版本安装到 iPhone 的最佳方式是啥?