如何使用csproj多目标.NET Core类库?


94

当.NET Core仍使用该project.json格式时,您可以构建一个针对多个框架的类库(例如net451,netcoreapp1.0)。

现在,正式的项目格式正在csproj使用MSBuild,您如何指定多个目标框架?我试图寻找这个在VS2017的项目设置,但我能只针对从.NET框架的核心在单一框架(它甚至没有列出我的其他完整的.NET框架版本已经安装) :

在此处输入图片说明


那不是应该的样子,您应该在下拉列表中获得.NETStandard 1.x选项。还不清楚这是如何发生的,请确保选择正确的项目模板以开始使用。应该是“类库(.NET标准)”。看起来您选择了Console App模板,然后开始更改属性,而不是正确的方法。如果您实际上使用的是“类库”模板,则安装无法顺利进行。
汉斯·帕桑

我实际上选择了类库(.NET Core)。
Gigi

2
对,因此如果要进行多目标定位,那将是错误的选择。您必须选择.NETStandard才能使该库在多个平台上可用。
汉斯·

这样就清除了。如果愿意,您可以根据自己的意见写出答案。
Gigi

Answers:


119

您需要手动编辑项目文件,并将s添加到默认的TargetFramework并将其基本上更改为TargetFrameworks。然后,你提到的名字对象; 分隔器。

您也可以手动或使用VS Nuget软件包管理器将Nuget软件包引用放入条件ItemGroup中。

这是您的.csproj的样子:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netstandard1.6;net452</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'net452'">
    <PackageReference Include="Microsoft.Azure.DocumentDB">
      <Version>1.12.0</Version>
    </PackageReference>
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.6'">
    <PackageReference Include="Microsoft.Azure.DocumentDB.Core">
    <Version>1.1.0</Version>
    </PackageReference>
  </ItemGroup>
</Project>

由于缺少文档,我最近要做的另一种解决方法是,我在VS2015中创建一个项目,并使用可用的文档和intellisense形成project.json,然后在VS2017中打开解决方案并使用内置升级。然后,我将查看csproj文件,以了解如何进行该配置。

在没有Moniker的情况下进行多目标更深奥的目标:

微软:

不建议使用PCL +

尽管支持PCL,但程序包作者应改为支持netstandard。.NET平台标准是PCL的发展,它使用一个单独的名称来表示跨平台的二进制可移植性,该名称未与可移植a + b + c此类静态名称绑定在一起。

如果你想针对便携式个人资料不具有预定义的绰号因此便携式个人档案也不能推断TargetFrameworkIdentifierTargetFrameworkVersionTargetFrameworkProfile。此外,不会自动定义编译器常量。最后,您必须添加所有程序集引用,默认情况下不提供任何程序集引用。

下面的示例摘自一个使用dynamic关键字的项目,因此它另外需要Microsoft.CSharp装配,因此您可以看到它如何引用不同的目标。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netstandard1.5;net40;portable40-net45+sl5+win8+wp8</TargetFrameworks>
  </PropertyGroup>

  <PropertyGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8+wp8'">
    <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
    <DefineConstants>$(DefineConstants);PORTABLE158</DefineConstants>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)'=='netstandard1.5'">
    <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
    <PackageReference Include="System.ComponentModel" Version="4.3.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)'=='net40'">
    <Reference Include="Microsoft.CSharp" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8+wp8'">
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Windows" />
  </ItemGroup>
</Project>

1
您是否需要通过手动编辑csproj来做到这一点,还是可以通过VS完成?
Gigi

1
@Gigi多重定位需要手动完成。Nuget包可以通过VS2017或手动完成。
阿布(Aboo)

2
我遇到了同样的问题,将s添加到<TargetFramework>后,一切正常。真希望这些东西能得到更好的记录。
Negorath

2
@AsadSaeeduddin很有可能是Resharper向您显示花体而不是Visual Studio。$(TargetFramework)仅用于使ItemGroup可用于特定框架/ Moniker。
阿布(Aboo)

2
@ORMapper如果NuGet包构造正确,则导入时应自动发生。这意味着如果NuGetPackageA已经支持多个框架,则无需将其放入条件项目组中。现在,如果您需要引用.net框架的PackageA和.net核心的PackageB,则需要将其放入条件项组中。截至今天(2017年10月),该界面中没有任何选项。
阿布(Aboo)

24

您可以.csproj为此手动编辑文件并设置TargetFrameworks(不设置TargetFramework)属性。

<TargetFrameworks>net451;netstandard1.4</TargetFrameworks>

例如,请参见EFCore.csprojhttps : //github.com/aspnet/EntityFrameworkCore/blob/951e4826a38ad5499b9b3ec6645e47c825fa842a/src/EFCore/EFCore.csproj


9
谢谢!它杀了我。在40年前布莱恩·科尼根(Brian Kernigan)撰写的“编程风格要素”中,他谈到了使用结尾处只有一个字母差异的变量的错误。如果名称为“ TargetFrameworkList”,那就更清楚了。
howardlo

您所指向的示例不包含<TargetFrameworks>属性。
RenniePet

@RenniePet,谢谢!项目文件已及时更改。我将链接更改为一个具体的提交,其中有<TargetFrameworks>。
夜行者

12

我实际上选择了类库(.NET Core)。

如果您的库需要在多个平台目标上工作,那不是您想要的项目模板。使用此项目模板,您的库只能在以.NETCore为目标的项目中使用。PCL库方法已淘汰,您现在必须选择.NETStandard。

您可以通过使用“类库(.NET Standard)”项目模板启动项目来实现。现在,您可以选择.NETStandard版本。当前的兼容性网格在这里

希望他们会保持链接文章的更新。不断变化的是,.NETStandard 2.0已被确定,但尚未发布。目标定于2017年第二季度(可能是春季末),目前显示已完成97%。我听到设计师说过不建议使用1.5或1.6,与2.0兼容不够


如果您对不同的目标框架有不同的依赖关系,它将如何工作?我的意思是,project.json您可以为目标框架指定特定的依赖关系。
Gigi

1
我90%确信您需要忘记这一点曾经存在过。这是一个混乱的混乱局面,只是引导.NETCore的权宜之计。使用我链接到的兼容性网格。
汉斯·帕桑

我也这么怀疑。非常感谢您的澄清!
Gigi

4
如果您有旧版代码,并且同时可以使用最新的完整框架版本或dotnetcore进行绿地开发,则@HansPassant多目标仍然是最佳选择。
Stefano Ricciardi

1
甚至未必一定是.NET Core友好对象。我正在使用Azure Function应用程序,但它们的.NET Core版本仅支持几个触发器。(我需要Service Bus触发器,所以我受制于.NET Framework,并且非常大的业务功能库可能会作为多目标出现。)Microsoft的平台目前陷入混乱。在现代上等同于DLL Hell。
McGuireV10

5

我做了多目标网络框架和netcore初学者指南,该指南从简单的1行修复开始,然后逐步介绍每种复杂情况。

最简单的方法是首先使netcore或netstandard目标工作。然后编辑csproj文件,并针对其他目标执行以下步骤。

  1. 了解csproj文件中的条件部分,以便可以为每个目标声明不同的依赖关系。为每个目标创建条件部分。
  2. <Reference />s通过读取缺少构建错误消息的内容,为所有netframework目标添加System。* dll。
  3. <PackageReference />s如果每个目标的NuGet依赖项不同,请处理它们。最简单的技巧是暂时还原为单个目标,以便GUI可以为您正确处理Nuget引用。
  4. 通过学习各种创造性的技术,变通方法和节省时间,来处理并非在所有目标上都可以编译的代码。
  5. 当添加更多目标的成本太高时,知道何时减少损失。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.