如何最好地针对多个版本的.NET框架进行定位?

50

我正在编写一个类库,并将其部署为NuGet包,这使我可以根据添加到的项目的.NET框架版本选择不同的程序集作为引用。这是一个非常好的功能,但我想知道是否可能有一个单一的类库项目,并针对多个.NET框架版本进行构建?

如果可能的话,我希望避免出现:

MyLibrary40.dllMyLibrary45.dll

因为两个项目将不得不共享很多代码。4.5版本将提供异步函数,这是一个4.5特性。

有人知道最佳方法是什么吗?我可以使用多个构建配置吗?还是必须走分开的项目路线?

如果我使用C ++,我可能会在仅受支持的配置周围使用多个配置和#if块,但我担心这会导致我具有执行不同操作的相同名称的两个程序集。

提前感谢!


但是,我已经找到了一个编译的解决方法,你可以查看我在问题中提供的链接,它们可能会对你的旅程有所帮助 - https://dev59.com/fW_Xa4cB1Zd3GeqP6_Qq - ilansch
2
@LarsKristensen,我想要一个项目文件,但是能够生成两个程序集 - 一个支持.NET 4.0,另一个支持.NET 4.5并添加一些异步函数 - 而不必创建单独的项目。 - Dave Kerr
我也曾问过这个问题,但没有得到明确的答案。也许您会有比我更好的答案,您需要的是配置管理器.. http://stackoverflow.com/questions/15321757/how-to-build-same-project-with-multiple-configuration-c-sharp-visualstudio2012 - ilansch
这可能也会有所帮助:https://dev59.com/aFTTa4cB1Zd3GeqPrlkr?rq=1 - ilansch
如果你尝试编译包含4.5关键词/方法调用的代码并将其作为4.0编译,我相信你会遇到问题。 - tsells
显示剩余7条评论
4个回答

40

你至少需要一个VisualStudio解决方案,其中包含两个项目(一个用于.NET 4,另一个用于.NET 4.5)。

将所有代码文件添加到.NET 4项目中,在另一个项目中将代码文件作为链接添加(使用“添加现有项...”对话框并选择“添加为链接”)

现在,您将所有的.NET 4.5代码和类添加到您的4.5项目中。

此外,您应该为您的项目定义自己的编译器开关(条件编译符号)。例如,NET4用于.NET 4项目,NET4.5用于.NET 4.5项目)

您可以在构建->常规->条件编译开关的项目设置中设置开关

在您的代码中,您可以使用这些开关来生成.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

5
非常感谢,我确实是这样做的。我有一个名为“JsonClient”的.NET Framework 4.5类库,它具有所有功能。.NET 4.0版本称为“JsonClientLite”,包含完全相同的代码,但不使用条件编译,而是每个类都有一个单独的带有Async方法的文件(因此在两个版本中都有JsonClient.cs,在主要版本中仅有JsonClientAsync.cs)-我在.NET 4.0版中使用文件的快捷方式,就像您描述的那样。我很满意这个方法的效果,它似乎是一种干净的方法-非常感谢您的答案! - Dave Kerr
1
我编写了https://github.com/CADbloke/CodeLinker来解决这个问题 - 它可以将现有项目中的项填充到新项目中。 - CAD bloke

17

一种简单的方法是在同一文件夹中添加另一个.csproj文件,并将其配置为构建不同版本的框架。这样可以避免添加文件链接,因为这两个项目本质上都是针对相同文件夹结构的视图

假设你有以下结构:

- MyLibrary\
  - MyLibrary.sln
  - MyLibrary\
    - MyLibrary.csproj
    - Program.cs

MyLibrary.csproj复制到同一文件夹并进行编辑以更改一些内容:

  • <ProjectGuid> 只需为此元素的值创建一个新的GUID
  • <TargetFrameworkVersion> 在这里指定替代版本,例如:v4.5v3.5
  • <OutputPath>(对于Debug和Release)将其设置为唯一路径,例如bin\ Debug\net45bin\ Debug\net45,以便每个项目的输出最终位于唯一位置

您还必须向非条件的<PropertyGroup>元素添加新元素,以便在并行构建期间两个项目不会在obj文件夹中发生冲突。这很重要,并可防止出现奇怪的竞争条件错误。

<PropertyGroup>
  <BaseIntermediateOutputPath>obj\net45\</BaseIntermediateOutputPath>

最后,将这个新项目添加到您现有的解决方案中。

这种方法与定义编译开关(如NET35NET45)以及使用#if NET35/#endif指令相辅相成。

两个使用此技术的开源项目分别是MetadataExtractorNetMQ。如果遇到问题,可以参考它们。


1
如果使用Visual Studio 2015,@DrewNoakes的答案仍然是前进的方式吗?或者现在有更好的方法来做到这一点吗?只是想知道。 - Jordy van Eijk
1
我在Visual Studio 2015中使用它。然而,一旦xproj/project.json的东西到位,那可能会是一个更好的针对多个平台的方式。 - Drew Noakes
1
@O.R.Mapper,是的,它并不完美。如果你幸运的话,一个项目将无法构建。否则,你可能会错过一个文件。但是在某些情况下,你需要这样做——也许你需要为某个目标版本中缺失的东西提供一个shim类。如果你知道更好的解决方案,我全听着呢。 - Drew Noakes
2
如果您使用接受的答案添加任何文件,您仍然需要记得在其他项目中链接它们。 - Joel McBeth
@DrewNoakes:这在某种程度上是正确的,但我可能仍然更喜欢通过条件编译来排除声明shim类的文件内容,而不是为不同的目标版本使用不同的项目文件。 - O. R. Mapper
显示剩余4条评论

5

我知道这是一个老问题,而且以前的回答并不合适...但现在可以使用共享项目,它在逻辑上与将项目添加为链接而不是单独添加每个文件相同。


不错的想法,但它有很多限制,最明显的是你的类库不能引用任何不是共享项目的内容。我想这是有道理的,但在每个NuGet包都是共享项目之前,在大多数情况下可能没有用处。 - mhenry1384
嗯,不太确定你在这里指的是什么。我可以创建一个共享库A和一个引用了A和Newtonsoft NuGet包的类库B。然后我可以在A中编写使用JObject的代码。这在VS2015和VS2017中都是正确的。 - Stephen Drew

1

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。- 来自审查 - Procrastinator
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接