如何将可移植类库 (PCL) 转换为 .NET Standard






3.40/5 (2投票s)
将可移植类库 (PCL) 转换为 .NET Standard 项目,并将 csproj 文件更改为新格式
引言
在本技巧中,我将向您展示如何将旧的 csproj 文件转换为新版本。 我还会告诉您在此过程中可能遇到的各种失败和障碍。
开始之前
如果您使用一些第三方 DLL,则必须确保它们支持所选的 netstandard 版本。 虽然不常见但有可能其中一个可能支持 PCL 但不支持 netstandard。 如果它们是通过 NuGet 安装的,您可以通过 NuGet 检查它们。 如果它们来自其他提供商,您必须自行检查。
原始的 csproj
原始的 csproj 文件如下所示
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{53561B15-7A94-4375-B9F5-4615EF3E6DB6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>***********</RootNamespace>
<AssemblyName>************</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile44</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Compile Include="Common\CloseRequest.cs" />
<Compile Include="Common\IAsyncOperations.cs" />
.............
</ItemGroup>
<ItemGroup>
<ProjectReference Include="***************">
<Project>{4C9A9142-43F2-4FDB-B041-C073AED6C4D6}</Project>
<Name>*****************</Name>
</ProjectReference>
.............
</ItemGroup>
<ItemGroup>
<Folder Include="Events\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\
Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
正如您所见,它是一个可移植的类库,目标是 profile44
。
新的 csproj
新的 csproj 文件非常简单
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DS.Publications.Common\DS.Publications.Common.csproj"/>
</ItemGroup>
</Project>
现在我们的目标是 .NET-Standard 1.6!
因此,您必须替换 ItemGroup
部分之前的所有内容,其中包含 ProjectReference
条目
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
请注意,这些文件不再列在 csproj 中。
在我的最后一个项目中,我使用 TFS 作为源代码控制,所以我需要这些 SAK(应该已经知道)行。 如果您使用其他源代码控制,您也可以删除这些行。
然后,您可以简化 ProjectReference
条目。 Name
和 GUID
是不必要的。
<ProjectReference Include="..\DS.Publications.Common\DS.Publications.Common.csproj"/>
嵌入式资源
不要删除带有 EmbeddedResource
或 Content
的 ItemGroup
-s!
<ItemGroup>
<EmbeddedResource Include="Resources\Welle320x480.png" />
</ItemGroup>
<ItemGroup>
<Content Include="ConverterExtensions.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ConverterExtensions.cs</LastGenOutput>
</Content>
</ItemGroup>
如果您删除这些行,png 文件仍将存在于项目中,但它不再是嵌入资源,并且 T4 模板不再是 Content。 但是不要担心,您可以在 Visual Studio 中再次设置这些属性。
NuGet 包
建议您重新安装 NuGet 包。 因此,请查看您的旧 *packages.config* 文件,看看之前有哪些条目。 记下它们并删除 *packages.config* 文件。 新的 csproj 格式可以将 NuGet 条目存储在 csproj 文件本身中。
所以我拥有以下条目
<packages>
<package id="CommonServiceLocator" version="1.3"
targetFramework="portable45-net45+win8" />
<package id="MvvmLightLibs" version="5.3.0.0"
targetFramework="portable45-net45+win8" />
</packages>
在我删除 *packages.config* 之后,我打开我的解决方案并再次安装 NuGet 包。 Visual Studio 会询问您 NuGet 条目应存储在哪里。 选择 csproj 的选项。
其他参考文献
如果您引用了其他第三方 DLL,您也必须保留这些行,但您可以简化它们。
<Reference Include="SuperThirdParty.dll">
<HintPath>..\Dependencies\netstandard1.6\SuperThirdParty.dll</HintPath>
</Reference>
或者您可以记下它们并在 Visual Studio 中再次分配它们。
测试项目
您还可以将测试项目转换为新格式。 但它不能以 netstandard1.6 为目标。 它必须以 netcoreapp1.1 为目标。 然后它可以引用 netstandard1.6 程序集。
AssemblyInfo.cs 问题
我假设您的旧项目中有一个 *AssemblyInfo.cs* 文件。 新的 csproj 格式以另一种方式工作,它不需要任何 *assemblyinfo.cs*。 程序集的属性存储在 csproj 文件中。 有一些默认值,并且 *AssemblyInfo.cs* 将在编译时生成。 因此,如果您也有原始的 *AssemblyInfo.cs*,则会在编译时出现错误,因为您两次拥有这些属性。 例如
error CS0579: Duplicate 'AssemblyVersion' attribute
要解决此问题,您可以选择以下之一
- 删除您的原始 *AssemblyInfo.cs* 并在项目属性页上手动设置属性
- 或者您可以保留原始的 *AssemblyInfo.cs* 并在 *csproj* 文件中禁用自动生成
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
其他项目
通常,您还有一些其他项目,它们引用您新的 netstandard 项目。 在这些项目中,您需要一个条目。
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
如果您没有此条目,您可能会仅在运行时遇到一些故障。 例如
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly
'System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
The located assembly's manifest definition does not match the assembly reference.
(Exception from HRESULT: 0x80131040)
较旧的 csproj 文件没有此标记,您必须手动插入它! 如果您更新现有项目,请记住这一点。
请参阅此链接。
引用程序集的引用
Visual Studio 中仍然存在一个错误:引用的 netstandard 项目的引用不会复制到输出文件夹。 您必须显式地引用它们! 至少在您的主/启动项目中。 否则,您只能在运行时收到异常,提示找不到 DLL。
建议您也在您的常规项目中安装 NuGet 包 "NetStandard Library
"。
netstandard1.3
我尝试在 WPF 项目中使用 netstandard1.6 库。 我总是在 XAML 设计器中遇到一些错误。 我有经验,WPF 只能与 netstandard1.3 库一起使用。
请参阅此链接。
感谢阅读!
我想知道您在转换项目时会得到什么样的经验。 请不要犹豫在评论中写下它们。