以前的项目格式使用的是 csproj 的格式,但是 .net core 支持使用 project.json 格式的项目文件,后来还是决定不使用这个格式。 VS2017 的项目格式更好读、更简单而且减少了 git 冲突。 本文来告诉大家如何从 VS2015 和以前的项目格式修改为 VS2017 项目格式。当前对新项目格式的命名是 SDK Style 风格的 csproj 项目文件格式。而在 VS2015 和以前的项目格式是 Franken-proj 格式
在迁移之前,我需要告诉大家,现在是2018年1月15日,最新的项目格式只有对下面的项目支持 现在是 2020年12月 好像啥项目都支持了
- class library projects 类库项目
- console apps 控制项目
- ASP.NET Core web apps asp 项目
- .NET Core .NET Core
- 还有其他所有的项目
自动化升级
因为好多小伙伴都在期望有自动化的工具去转换,因此 dotnet 基金会特别推出了转换工具
详细请看官方文档 将 WPF 应用升级到 .NET 5 - .NET Core
使用方法如下
这是一个 dotnet tool 工具,使用之前先使用下面命令进行安装。这是一个在 GitHub 上完全开源的仓库,请看 https://github.com/dotnet/try-convert
接着进入到需要转换的项目所在的文件夹
使用下面命令进行自动化转换
默认能将 csproj 转换好,但是转换完成之后,也许会构建不通过,如提示 特性重复的编译出现 CS0579 重复,请看下面提示内容
解决方法是删除 AssemblyInfo.cs 文件的内容。特性文件不删除也可以,请使用解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题的方法
详细请看 dotnet 自动迁移 VS 2017 以前的 csproj 转为 dotnet core 的 SDK Style 风格工具
其他细节部分还请看手动修改
手动修改
对于 UWP 和 WPF ,有 xaml 的项目是没有很好支持 现在是 2020年12月 好像支持不错
现在很多项目,测试使用的项目都使用新格式,建议在自己用来测试的项目试试
建议从一个测试项目试试,先做好提交,如果失败可以回滚。 不用试试了,我都玩了三年了
如果创建是库项目,那么 csproj 文件只有下面的代码就可以完成了
如果创建的是控制项目,那么只有下面的代码
如果创建的是测试项目,那么只有下面的代码
如果是 WinForms 或 WPF 项目,那么只有下面的代码
如果想知道新格式和之前的区别,如何从以前的格式迁到新的格式,请继续阅读本文
下面从项目的第一行开始来告诉大家如何一步步迁移。当前还没有一个可以做到自动化的迁移工具,但是有一个快捷的方式是重新新建项目,然后一点点将原有项目的内容通过在 VS 上可视化的步骤加回来。本文会告诉大家的是如何编辑 csproj 文件,而不是在 VS 上通过点一点完成,本文更适合高级的开发者
原来的第一行的代码大概内容如下
新的格式的第一行内容如下
或者对于 WPF 来说是如下格式,关于 WPF 部分放在本文最后
从第一行可以看到新的格式的代码比较少,而实际上除了第一行之外,后面的内容有着更大的简化
其实建议大家重新创建一个项目,然后把文件放进去,安装 Nuget 不然需要修改比较多
必须删除的内容
下面的代码必须删除,因为新的 SDK 风格的项目格式不再需要了
还需要删除 AssemblyInfo.cs 文件,不然编译出现 CS0579 重复,请看下面提示内容
特性文件不删除也可以,请使用解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题的方法
必须修改
需要修改平台框架的代码
这是以前的代码
需要修改为下面的代码
如果是 v4.5.2 ,请修改为 net452 ,如果是 v4.6 就修改为 net46 详细请看 dotnet 新项目格式与对应框架预定义的宏
添加文件
现在新的格式可以使用通配添加文件,例如在文件夹的所有的代码都需要添加,可以使用这个方式
如果啥都不做,默认的 SDK 风格的项目格式已经包含了如下的引用
所以添加的 cs 文件都会添加到编译,需要删除这个代码才可以不编译一些文件,也就是原先写的添加文件都需要删除,如果不想删除可以使用 EnableDefaultCompileItems 设置不添加 cs 文件。否则将会提示文件重复
对 WPF 项目需要额外设置 EnableDefaultPageItems 不包含 Page 解决
更多默认的行为请看 Roslyn 禁止 sdk style csproj 默认引用 Compile 代码文件
项目引用
之前的方式需要添加很多代码,如引用 ClassLibrary1 的项目,需要写下面的代码
Project 这个可以表示这是一个类库或一个其他的项目,因为新的项目不需要这个,所以在新建文件的时候就不知道给哪个项目,这是比较差的
新的格式就需要下面的代码,不需要使用 Project 和 Name 这两个元素
如果引用的项目有依赖,以前的格式需要把引用写在文件,现在不需要添加引用
假如有 A 引用 B ,B 引用 C ,那么之前的A项目文件就是这样
现在的文件格式不需要写引用的依赖,只需要写入最顶层的依赖就可以了
而原先存在的一些引用,如 System.Net.Http 等可以使用 dotnet 新 sdk style 项目格式的一些命名空间和引用 的方法引用
引用包
之前的 Nuget 引用需要添加 packages.config 和 csproj 才可以使用,现在的 Nuget 4 可以直接在 csproj 添加引用
这是之前的格式
新的格式写引用,不需要 packages.config 文件,这样减少了找不到nuget的坑,下面代码就是新的格式,可以看到代码减少1/2
这个格式可以在git冲突比较容易看到哪里需要修改,所以解决冲突很简单
在 nuget 2 的引用,如果引用了包A,他引用了 B 库,那么就需要在 packages.config 引用写了这几个项目
现在 Nuget 4 需要写引用的库,不需要写他的引用,所以可以减少代码,添加了id和版本就好
如果在迁移过程遇到诡异的问题,请看将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - walterlv
删除多余文件
现在 VisualStudio 2017 项目格式不需要使用 AssemblyInfo 包含一些值,所以现在编译 VisualStudio 会发现重复定义了一些值,需要删除 Properties/AssemblyInfo.cs
文件。
如果只有需要定义一些全局的特性,那么直接新建一个类写就好。
如果不想删除,请设置 GenerateAssemblyInfo 属性
详细请看 解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题
删除的时候小心属于 WPF 的 ThemeInfo 特性和 COM 不能删除
输出注释文档
如果需要输出注释文档文件,也就是 xx.xml 注释文件,在以前的代码是在属性页面,点击生成xml选项就可以生成的注释文档,现在新的格式和之前有些不一样,可以通过添加下面的代码生成xml注释文档文件,请看代码
这里的$(Configuration)
就是用到了宏,他会替换当前编译的是 Debug 还是 release ,所以对于所有的项目都可以使用这个来生成 xml 注释文档文件
或者使用 OutputPath 相同的文件夹,因为可能是自己定义了 OutputPath 下面代码就自己修改了不在当前的文件夹
注意这时需要让 OutputPath 在 DocumentationFile 之前,否则拿到的值是默认的值
更简易的方法,可以无视路径的方法是使用 GenerateDocumentationFile 属性
将 XML 输出到 NuGet 包的方法请看 Roslyn 在 NuGet 包中放注释 xml 文件的方法
如果还有其他的文件也需要放入 NuGet 包,请看 Roslyn 打包自定义的文件到 NuGet 包
多个框架
如果需要同时打包出 dotnet standard 和 dotnet framework 的包,就需要使用下面的方法。
因为现在存在一些项目是使用多个开发框架,这时就需要修改TargetFramework
为TargetFrameworks
也就是写为复数的TargetFrameworks
,把里面的一个框架修改为多个,请看下面
如果想知道每个平台的缩写,请看Target frameworks 或我的博客 dotnet 新项目格式与对应框架预定义的宏
.NET Standard
- netstandard1.0
- netstandard1.1
- netstandard1.2
- netstandard1.3
- netstandard1.4
- netstandard1.5
- netstandard1.6
- netstandard2.0
.NET Core
- netcoreapp1.0
- netcoreapp1.1
- netcoreapp2.0
- netcoreapp2.1
.NET Framework
- net11
- net20
- net35
- net40
- net403
- net45
- net451
- net452
- net46
- net461
- net462
- net47
- net471
- net472
Universal Windows Platform
- uap [uap10.0]
- uap10.0 [win10] [netcore50]
使用条件判断
因为在多个框架,存在一些框架不能引用的库,而在一些框架需要这些库,如 ValueTuple ,就需要在引用的时候添加条件
添加条件可以使用这样的代码Condition=" '$(TargetFramework)' == 'net40'
把 net40 修改为你希望的框架就在指定的框架引用库。
如果通过条件还可以在某些框架引用或不引用某些文件。
在代码可以通过默认的宏来判断当前是哪个框架,默认的宏就是上面的缩写的大写
不同框架的宏请看下面
.NET Framework
- NET20
- NET35
- NET40
- NET45
- NET451
- NET452
- NET46
- NET461
- NET462
- NET47
- NET471
- NET472
.NET Standard
- NETSTANDARD1_0
- NETSTANDARD1_1
- NETSTANDARD1_2
- NETSTANDARD1_3
- NETSTANDARD1_4
- NETSTANDARD1_5
- NETSTANDARD1_6
- NETSTANDARD2_0
.NET Core
- NETCOREAPP1_0
- NETCOREAPP1_1
- NETCOREAPP2_0
- NETCOREAPP2_1
更多宏细节请看 dotnet 新项目格式与对应框架预定义的宏
参见:让一个 csproj 项目指定多个开发框架 - walterlv
迁移 WPF 项目
如果需要迁移 WPF 项目,那么先记下自己的引用,最好是截图,然后卸载项目。编辑项目文件,使用下面的代码代替
保存重新加载,可能需要修改平台,我这里使用 net45 ,大家按照原来的需要修改。
看一下缺少了哪些引用再自己添加。
稍微解释一下上面的代码,在一开始使用的 OutputType 是告诉 VisualStudio 生成一个窗口应用程序。因为默认生成的是 dll ,而在本文上面也告诉大家设置控制台输出是使用下面代码
对于 WPF 是窗口程序,如果使用了上面的设置,就会在启动的过程先出现控制台窗口,然后在显示主界面。为了让 WPF 窗口直接显示而不是先显示控制台窗口,需要把上面代码修改为
如果此时提示找不到 App.xaml 请在 csproj 添加下面代码
在 WPF 还有很多窗口页面,这些代码使用 xaml 来写,需要把 xaml 和 xaml.cs 对应,所以需要使用下面代码
上面这个代码的意思是对于 xaml 文件的编译和折叠,如折叠 Foo.xaml 和 Foo.xaml.cs 文件。现在对于 UWP 项目,使用上面的方法是编译不通过。如果需要支持 UWP 的 VisualStudio 2017 项目格式,请看 新 csproj 对 WPF/UWP 支持不太好?有第三方 SDK 可以用!MSBuild.Sdk.Extras - walterlv。如果不想点击网站,那么就请看代码
现在官方支持使用下面代码迁移 WPF 项目
核心是 Sdk="Microsoft.NET.Sdk.WindowsDesktop"
和 <UseWPF>true</UseWPF>
两句话
如果需要引用 WinForms 项目,请添加 UseWindowsForms 属性
把项目文件修改为上面的代码就可以支持 dotnet 4.7 和 UWP 项目
在新 SDK Style 风格 csproj 项目格式文件使用 WPF 和 WinForms 引用
如上面描述,在添加了 .NET Core 3.1 和以下版本或 .NET Framework 版本,可以使用 Microsoft.NET.Sdk.WindowsDesktop
构建
如果有 .NET 5 的引用支持,请使用 net5.0-windows 框架,于是一个多框架支持的项目格式,同时引用 WPF 和 WinForms 的新 SDK Style 风格的项目格式文件内容可以是如下
库替换
System.Management
替换为 System.Management 的 NuGet 包即可
System.ValueTuple
在 dotnet framework 4.5 下不支持 System.ValueTuple 需要手动加上此库。在此库里面内部判断了版本,因此使用如下两个方式效果是相同的
或者不加上 TargetFramework 判断。在 System.ValueTuple 库里面加上了对 TargetFramework 的判断
参见:Old csproj to new csproj: Visual Studio 2017 upgrade guide
将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - walterlv
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。