不同平台框架项目使用同一套代码,一次编译生成多个框架类库
目录
需要先了解的东西
分析
- 使用.NET 可移植性分析器工具分析项目依赖
- .NET 可移植性分析器工具有关博客
- 根据分析结果以及建议,到这个网站可以根据fx框架下类型名查找对应的nuget包,来替代不兼容的引用
- 重新组织项目依赖,整理各个框架公共的代码文件和其他平台不支持的功能的代码文件,必要时可将一个文件分成多个多个文件
- 由于我这里已经是多个分开的项目,就省了分析代码这一步,直接分析文件应该归属哪些项目,哪些独有的
添加PropertyGroup
多目标平台
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;net45;netstandard2.0</TargetFrameworks>
</PropertyGroup>
</Project>
编译符号和输出目录设置
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Debug|AnyCPU|net45'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<DocumentationFile>..\..\Bin\net45\XCode.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Release|AnyCPU|net45'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>..\..\Bin\net45\XCode.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)'=='Debug|AnyCPU|netstandard2.0'">
<OutputPath>..\..\Bin\</OutputPath>
<DocumentationFile>..\..\Bin\netstandard2.0\XCode.xml</DocumentationFile>
<DefineConstants>TRACE;DEBUG;NETSTANDARD2_0;__CORE__</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)'=='Release|AnyCPU|netstandard2.0'">
<OutputPath>..\..\Bin\</OutputPath>
<DocumentationFile>..\..\Bin\netstandard2.0\XCode.xml</DocumentationFile>
<DefineConstants>TRACE;RELEASE;NETSTANDARD2_0;__CORE__</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Debug|AnyCPU|net40'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET4</DefineConstants>
<DocumentationFile>..\..\Bin\net40\XCode.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Release|AnyCPU|net40'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE;NET4</DefineConstants>
<DocumentationFile>..\..\Bin\net40\XCode.xml</DocumentationFile>
</PropertyGroup>
添加依赖
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' Or '$(TargetFramework)' == 'netstandard2.0' ">
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Session" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net40'">
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NewLife.Core\NewLife.Core.csproj">
<Name>NewLife.Core</Name>
</ProjectReference>
</ItemGroup>
- 如果依赖项那里显示感叹号,关掉项目重新打开即可
代码文件处理
- 将前面分析好的代码文件分情况做排除,由于项目里面的文件自动显示在解决方案,不用显式包含文件,只需要根据目标平台做好排除即可
主副平台项目文件处理
全部平台都包含
- MSBuild项目文件会自动包含项目文件下面的所有文件,不必处理
一个或多个平台包含
- 在所有不包含的此文件的平台的ItemGroup中移除
没有平台包含
- 没有项目包含此文件为什么还有放在项目文件夹?我也不知道,在全局ItemGroup移除即可
最后
- 生成看看还有什么错误,看情况解决,比如PropertyGroup设置了文件版本信息,同时引用了
/Properties/AssemblyInfo.cs
导致报错等等。 - 合并之前的项目文件
- 合并之后的项目文件
- 合并第一个项目的时候,简直一团糟,本来所有项目都不包含的代码都涌进来,有的文件只是一个项目有。合并到第二个,先做好分析,什么文件该引用还是排除,有条理很快就完成,处理好文件引用之后一次性生成成功,没有第一个项目合并的时候一千多个错误
补充
自动生成内部版本号
以前的写法是在/Properties/AssemblyInfo.cs里通过
[assembly: AssemblyVersion("2.3.*")]
这样的形式生成,但是现在默认关闭这个功能了,如果我们直接指定<AssemblyVersion>9.8.*</AssemblyVersion>
会警告错误,加上<Deterministic>False</Deterministic>
即可为什么默认关闭?请了解下Roslyn中的确定性构建,我不是很懂,不,是根本看不懂
其它生成方式、汇编内部版本号后面两位的生成规则,请看使用Visual Studio时是否可以自动增加文件构建版本、Visual Studio 2017中的自动版本控制(.NET Core)、如何有一个自动递增版本号(Visual Studio)
msbuildtasks也了解一下,如果要兼容以前的内部版本号生成规则,可自己动手
nuget包相关
- 静态文件如何指定复制行为等等,或许你会发现安装nuget之后希望能编辑的文件仅仅只是一个链接而已,如何让它包含在项目里面呢,参考NuGet ContentFiles揭秘,带回解决方案级包的讨论
- PackageReference方式作为包管理格式,安装时不支持执行install.ps1等powershell相关脚本,init.ps1在解决方案第一次安装时可用。vs2017中,已不支持此功能,NuGet 3 - 什么和为什么-Powershell安装和卸载脚本
- 关于nuget包安装的相关行为估计都可以通过msbuild属性或者任务来搞定,这一切都是可以通过命令行来执行的,方便跨平台使用吧
- msbuildtasks也了解一下,可以代替ps1脚本完成你想做的事