zoukankan      html  css  js  c++  java
  • 2019-10-15-从以前的项目格式迁移到-VS2017-新项目格式

    title author date CreateTime categories
    从以前的项目格式迁移到 VS2017 新项目格式
    lindexi
    2019-10-15 14:9:27 +0800
    2018-2-13 17:23:3 +0800
    VisualStudio

    以前的项目格式使用的是 csproj 的格式,但是 .net core 支持使用 project.json 格式的项目文件,后来还是决定不使用这个格式。 VS2017 的项目格式更好读、更简单而且减少了 git 冲突。 本文来告诉大家如何从 VS2015 和以前的项目格式修改为 VS2017 项目格式。

    在迁移之前,我需要告诉大家,现在是2018年1月15日,最新的项目格式只有对下面的项目支持

    • class library projects 类库项目
    • console apps 控制项目
    • ASP.NET Core web apps asp 项目
    • .NET Core .NET Core

    对于 UWP 和 WPF ,有 xaml 的项目是没有很好支持,如果你的项目是 WPF 的,那么请不要再往下看。如果想迁移 WPF 或 UWP 请看 将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - walterlv

    现在很多项目,测试项目都使用新格式,建议在测试项目试试

    建议从一个测试项目试试,先做好提交,如果失败可以回滚。

    如果创建是库项目,那么 csproj 只有下面的代码

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net46</TargetFramework>
      </PropertyGroup>
    </Project>

    如果创建的是控制项目,那么只有下面的代码

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net46</TargetFramework>
      </PropertyGroup>
    </Project>

    如果创建的是测试项目,那么只有下面的代码

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net46</TargetFramework>
      </PropertyGroup>
      <ItemGroup>
        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
        <PackageReference Include="xunit" Version="2.2.0" />
        <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
      </ItemGroup>
    </Project>

    如果想知道新格式和之前的区别,如何从以前的格式迁到新的格式,请看下面

    下面从项目的第一行开始

    原来的第一行是

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    新的格式的第一行是

    <Project Sdk="Microsoft.NET.Sdk">

    可以看到新的格式的代码比较少

    其实建议大家重新创建一个项目,然后把文件放进去,安装 Nuget 不然需要修改比较多。

    必须删除

    下面的代码必须删除

    <!-- usually at the top of the file -->
    <!-- 下面的代码一般在文件的最前 -->
    <Import Project="$(MSBuildExtensionsPath)$(MSBuildToolsVersion)Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)$(MSBuildToolsVersion)Microsoft.Common.props')" />
    
    <!-- usually at the bottom -->
    <!-- 一般在文件的最后面 -->
    <Import Project="$(MSBuildToolsPath)Microsoft.CSharp.targets" />
    <Import Project="$(VSToolsPath)TeamTestMicrosoft.TestTools.targets" Condition="Exists('$(VSToolsPath)TeamTestMicrosoft.TestTools.targets')" />

    还需要删除 AssemblyInfo.cs 文件,不然编译出现 CS0579 重复,请看下面

        Error CS0579: “System.Reflection.AssemblyCompanyAttribute”特性重复 (1, 1)

    特性文件不删除也可以,请使用解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题

    必须修改

    需要修改平台的代码

    这是以前的代码

    <PropertyGroup>
      <!-- ... -->
      <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    </PropertyGroup>

    需要修改为下面的代码

    <PropertyGroup>
      <TargetFramework>net452</TargetFramework>
    </PropertyGroup>

    如果是 v4.5.2 ,请修改为 net452 ,如果是 v4.6 就修改为 net46

    添加文件

    现在新的格式可以使用通配添加文件,例如在文件夹的所有的代码都需要添加,可以使用这个方式

    <Compile Include="lindexi*.cs" />

    默认是下面代码

    <!-- the defaults -->
    <Compile Include="***.cs" />
    <EmbeddedResource Include="***.resx" />

    所以添加的 cs 文件都会添加到编译,需要删除这个代码才可以不编译一些文件

    项目引用

    之前的方式需要添加很多代码,如引用 ClassLibrary1 的项目,需要写下面的代码

    <ProjectReference Include="..ClassLibrary1ClassLibrary1.csproj">
      <Project>{2C7DF870-5B35-49EF-963D-EE1E72C3177E}</Project>
      <Name>ClassLibrary1</Name>
    </ProjectReference>

    Project 这个可以表示这是一个类库或一个其他的项目,因为新的项目不需要这个,所以在新建文件的时候就不知道给哪个项目,这是比较差的

    新的格式就需要下面的代码

    <ProjectReference Include="..ClassLibrary1ClassLibrary1.csproj" />

    如果引用的项目有依赖,以前的格式需要把引用写在文件,现在不需要添加引用

    假如有 A 引用 B ,B 引用 C ,那么之前的A项目文件就是这样

    <ProjectReference Include="..ProjectBProjectB.csproj">
      <Project>{A900C843-8340-421B-B4F0-6C65A0D093C4}</Project>
      <Name>ProjectB</Name>
    </ProjectReference>
    <ProjectReference Include="..ProjectCProjectC.csproj">
      <Project>{871AC142-FC46-49F5-A5E0-90436648B9C5}</Project>
      <Name>ProjectB</Name>
    </ProjectReference>

    现在的文件格式不需要写引用

    <ProjectReference Include="..ProjectBProjectB.csproj" />

    引用包

    之前的 Nuget 引用需要添加 packages.config 和 csproj 才可以使用,现在的 Nuget 4 可以直接在 csproj 添加引用

    这是之前的格式

    <Import Project="....packagesxunit.runner.visualstudio.2.2.0uild
    et20xunit.runner.visualstudio.props" Condition="Exists('....packagesxunit.runner.visualstudio.2.2.0uild
    et20xunit.runner.visualstudio.props')" />
    
    <ItemGroup>
      <None Include="packages.config" />
    
      <Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
      <HintPath>....packagesMySql.Data.6.9.9libnet45MySql.Data.dll</HintPath>
      <Private>True</Private>
    </Reference>
    </ItemGroup>

    新的格式写引用,不需要 packages.config 文件,这样减少了找不到nuget的坑,下面代码就是新的格式,可以看到代码减少1/2

    <ItemGroup>
      <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
      <PackageReference Include="MySql.Data" Version="6.9.9" />
    </ItemGroup>

    这个格式可以在git冲突比较容易看到哪里需要修改,所以解决冲突很简单

    在 nuget 2 的引用,如果引用了包A,他引用了 B ,那么就需要在 packages.config 引用写了这几个项目

    <?xml version="1.0" encoding="utf-8"?>
    <!-- in packages.config -->
    <packages>
      <package id="A" version="2.2.0" targetFramework="net452" />
      <package id="B" version="2.0.1" targetFramework="net452" />
    </packages>

    现在 Nuget 4 需要写引用的库,不需要写他的引用,所以可以减少代码,添加了id和版本就好

    <ItemGroup>
      <PackageReference Include="A" Version="2.2.0" />
    </ItemGroup>

    如果在迁移过程遇到诡异的问题,请看将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - walterlv

    删除多余文件

    现在 VisualStudio 2017 项目格式不需要使用 AssemblyInfo 包含一些值,所以现在编译 VisualStudio 会发现重复定义了一些值,需要删除 Properties/AssemblyInfo.cs 文件。

    如果只有需要定义一些全局的特性,那么直接新建一个类写就好。

    输入注释

    如果需要输出注释,在以前的代码是在属性页面,点击生成xml,现在新的格式和之前有些不一样,可以通过添加下面的代码生成xml,请看代码

      <PropertyGroup>
        <DocumentationFile>bin$(Configuration)$(TargetFramework)$(AssemblyName).xml</DocumentationFile>
      </PropertyGroup>

    这里的$(Configuration)就是用到了宏,他会替换当前编译的是 Debug 还是 release ,所以对于所有的项目都可以使用这个来生成 xml。

    或者使用 OutputPath 相同的文件夹,因为可能是自己定义了 OutputPath 下面代码就自己修改了不在当前的文件夹

      <PropertyGroup>
        <OutputPath>....bin$(Configuration)</OutputPath>
        <DocumentationFile>$(OutputPath)$(TargetFramework)$(AssemblyName).xml</DocumentationFile>
      </PropertyGroup>

    注意这时需要让 OutputPath 在 DocumentationFile 之前,否则拿到的值是默认的值

    多个框架

    如果需要同时打包出 dotnet standard 和 dotnet framework 的包,就需要使用下面的方法。

    因为现在存在一些项目是使用多个开发框架,这时就需要修改TargetFrameworkTargetFrameworks也就是写为复数的TargetFrameworks,把里面的一个框架修改为多个,请看下面

      <PropertyGroup>
        <TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
      </PropertyGroup>

    如果想知道每个平台的缩写,请看Target frameworks

    .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 修改为你希望的框架就在指定的框架引用库。

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

    如果通过条件还可以在某些框架引用或不引用某些文件。

    在代码可以通过默认的宏来判断当前是哪个框架,默认的宏就是上面的缩写的大写

        static void Main()
        {
    #if NET40
            Console.WriteLine("Target framework: .NET Framework 4.0");
    #elif NET45  
            Console.WriteLine("Target framework: .NET Framework 4.5");
    #endif
        }

    不同框架的宏请看下面

    .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

    参见:让一个 csproj 项目指定多个开发框架 - walterlv

    迁移 WPF 项目

    如果需要迁移 WPF 项目,那么先记下自己的引用,最好是截图,然后卸载项目。编辑项目文件,使用下面的代码代替

    <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
      <PropertyGroup>
        <LanguageTargets>$(MSBuildToolsPath)Microsoft.CSharp.targets</LanguageTargets>
        <TargetFrameworks>net45;</TargetFrameworks>
        <OutputType>WinExe</OutputType>
      </PropertyGroup>
     
      <ItemGroup>
        <Compile Update="***.xaml.cs">
          <DependentUpon>%(Filename)</DependentUpon>
        </Compile>
        <Page Include="***.xaml">
          <SubType>Designer</SubType>
          <Generator>MSBuild:Compile</Generator>
        </Page>
    
        <Resource Include="***.png" />
        <Resource Include="***.jpg" />
        <Resource Include="***.cur" />
        <Resource Include="***.ps" />
        <None Include="***.fx" />
        <None Include="***.md" />
        <None Include="***.ruleset" />
      </ItemGroup>
     
      <ItemGroup>
        <Reference Include="System" />
        <Reference Include="System.Data" />
        <Reference Include="System.Xml" />
        <Reference Include="Microsoft.CSharp" />
        <Reference Include="System.Core" />
        <Reference Include="System.Xml.Linq" />
        <Reference Include="System.Data.DataSetExtensions" />
        <Reference Include="System.Net.Http" />
        <Reference Include="System.Xaml"/>
        <Reference Include="WindowsBase" />
        <Reference Include="PresentationCore" />
        <Reference Include="PresentationFramework" />
      </ItemGroup>
    </Project>

    保存重新加载,可能需要修改平台,我这里使用 net45 ,大家按照原来的需要修改。

    看一下缺少了哪些引用再自己添加。

    稍微解释一下上面的代码,在一开始使用的 OutputType 是告诉 VisualStudio 生成一个窗口应用程序。因为默认生成的是 dll ,而在本文上面也告诉大家设置控制台输出是使用下面代码

        <OutputType>Exe</OutputType>
    

    对于 WPF 是窗口程序,如果使用了上面的设置,就会在启动的过程先出现控制台窗口,然后在显示主界面。为了让 WPF 窗口直接显示而不是先显示控制台窗口,需要把上面代码修改为

        <OutputType>WinExe</OutputType>

    在 WPF 还有很多窗口页面,这些代码使用 xaml 来写,需要把 xaml 和 xaml.cs 对应,所以需要使用下面代码

        <Compile Update="***.xaml.cs">
          <DependentUpon>%(Filename)</DependentUpon>
        </Compile>
        <Page Include="***.xaml">
          <SubType>Designer</SubType>
          <Generator>MSBuild:Compile</Generator>
        </Page>

    上面这个代码的意思是对于 xaml 文件的编译和折叠,如折叠 Foo.xaml 和 Foo.xaml.cs 文件。现在对于 UWP 项目,使用上面的方法是编译不通过。如果需要支持 UWP 的 VisualStudio 2017 项目格式,请看 新 csproj 对 WPF/UWP 支持不太好?有第三方 SDK 可以用!MSBuild.Sdk.Extras - walterlv。如果不想点击网站,那么就请看代码

    <Project Sdk="MSBuild.Sdk.Extras/1.5.4">
      <PropertyGroup>
        <TargetFrameworks>net47;uap10.0</TargetFrameworks>
      </PropertyGroup>
    </Project>

    把项目文件修改为上面的代码就可以支持 dotnet 4.7 和 UWP 项目

    参见:Old csproj to new csproj: Visual Studio 2017 upgrade guide

    将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - walterlv

  • 相关阅读:
    [笔迹]java范型
    转:APNS设置
    orientation in a UIView add to a UIWindow
    no password for ssh
    webservice soap
    set the region for all annotation
    iOS与Java服务器GZip压缩问题【转】
    useful commands for Mac / iOS
    textView使用总结
    总结(不断更新)
  • 原文地址:https://www.cnblogs.com/lindexi/p/12085713.html
Copyright © 2011-2022 走看看