最新版本号[免费下载]

如何移植.NET Framework项目至.NET Core?

作者:本站编辑 发布时间:2018-10-09 来源:佚名 点击数:

公司的项目一直采用.NET框架来开发Web项目。目前基础类库均为.NET Framework 4.6.2版本。Caching, Logging,DependencyInjection,Configuration等基础设施相关的依赖库一直和官方保持同步,目前是1.1版本。.NET Core越来越趋于稳定,新的开发工具也在三月份发布。因此,计划将.NET Framework移植至.NET Core/Strandard。目的是使基于.NET开发的Web应用可以跨平台运行。

按应用场景将公司的项目分为基础类库,基础服务和应用项目。基础类库以包的形式提供各类基础功能。基础服务通过Wcf项目搭建或者通过Web API项目搭建。应用项目则是Web Mvc项目为主。基础类库和基础服务是以一个一个解决方案的形式存在。每个解决方案的结构,包含一个或者多个类库项目,一个或多个控制台项目,它们分别用于功能实现、单元测试、功能演示。如果全部要移植,那么优先级应该是基础类库 -> 基础服务 -> 应用项目。此次移植的对象是基础类库。

基础类库最终会以包的形式通过NuGet发布出去,目前只面向.NET Framework框架。移植的目标之一,是让包也能被面向.NET Core、.NET Standard框架的项目引用。结合官方资料,我选择了直接迁移的方案。即直接将项目文件转换为新的基于.NET Core的项目文件。下面详细说明移植的细节。

1. 新建基于.NET Core的项目。

首先重命名现有项目文件*.csproj为*.Net46.csproj。然后使用VS2017新建一个新的基于.NET Core的项目,项目类型可以是“类库(.Net Core)”或者“类库(.Net Standard)”。注意,VS2017会提示存在同名目录,所以创建时可以输入一个不同的名称,然后手工调整回来。

1.png

 

2. 编辑项目文件,使之支持面向多个目标框架。

通过VS2017 RC新建的项目,“类库(.Net Core)”或者“类库(.Net Standard)”,默认只有一个目标框架。我们可以编辑项目文件,使之支持面向多个目标框架。如支持目标框架为.NET Standard 1.4、.Net Core App 1.0和.NET Framework 4.5,则这样来修改。

1
2
3
4
5
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
      <TargetFrameworks>netstandard1.4;netcoreapp1.0;net45</TargetFrameworks>
    </PropertyGroup>
</Project>

注意,官方文档中提供了.NET支持的目标框架列表,你可以查询更多其他的目标框架。如果要兼容较低版本的框架,则目标框架版本不宜设置过高。如“net45”可用于.NET Framework 4.5 ~ 4.6.2等版本。如“net46”则只能用于.NET Framework 4.6 ~ 4.6.2等版本。

3. 修改应用程序代码相关API,使之支持多个目标框架。

a. 因目标框架提供的API不相同。故必要时可添加条件编译符号以便支持不同的运行时版本。

以下是常见的条件编译符号列表。

.NET Framework 2.0 --> NET20
.NET Framework 3.5 --> NET35
.NET Framework 4.0 --> NET40
.NET Framework 4.5 --> NET45
.NET Framework 4.5.1 --> NET451
.NET Framework 4.5.2 --> NET452
.NET Framework 4.6 --> NET46
.NET Framework 4.6.1 --> NET461
.NET Framework 4.6.2 --> NET462
.NET Standard 1.0 --> NETSTANDARD1_0
.NET Standard 1.1 --> NETSTANDARD1_1
.NET Standard 1.2 --> NETSTANDARD1_2
.NET Standard 1.3 --> NETSTANDARD1_3
.NET Standard 1.4 --> NETSTANDARD1_4
.NET Standard 1.5 --> NETSTANDARD1_5
.NET Standard 1.6 --> NETSTANDARD1_6

 关于条件编译符号的应用,如以下代码:

using System;
using System.IO;
namespace Baza.NetStandardTester
{
    public class PathHelper
    {
        public string BaseDirectory { get; set; }
        public PathHelper()
        {
#if NET45
            BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
#endif
        }
        public string GetRootedPath(string path)
        {
            string rootedPath = path ?? string.Empty;
            if (!Path.IsPathRooted(rootedPath))
            {
                if (string.IsNullOrEmpty(BaseDirectory))
                    throw new ArgumentNullException("请先设置BaseDirectory属性");
                rootedPath = Path.Combine(BaseDirectory, rootedPath);
            }
            string directory = Path.GetDirectoryName(rootedPath);
            if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            return rootedPath;
        }
    }
}

代码说明,PathHelper提供GetRootedPath方法用于根据相对路径计算出绝对路径。当运行时为.NET Core时,BaseDirectory属性需要手动设置。当运行时为.NET Framework 4.5时,由构造器对BaseDirectory属性进行赋值。注意System.AppDomain.CurrentDomain.BaseDirectory用于获取托管程序执行路径,类AppDomain只存在于.NET Framework中。

b. .NET Standard是个基于包的框架。当你需要某个API时,如IDataReader,你需要安装System.Data.Common包。如果是使用.NET Framework,则在命名空间System.Data下可以找到IDataReader而无需按照包。借助https://packagesearch.azurewebsites.net/工具,你可以快速定位某个API在哪个包中。

c. 基于.NET Core的项目,包版本号和其他元数据,都存储在*.csproj中,不会使用AssemblyInfo.cs文件,即移植时,这个文件可以删除。但是.NET Framework项目还是会继续使用该文件。

4. 同一解决方案,类库间的引用策略。

在引用类库时,要注意目标框架的兼容问题。如,“类库(.Net Standard)”项目,能够被.NET Core App、.NET Framework和其他.NET Standard项目引用。这个是因为.NET Core App和.NET Framework都支持相应版本的.NET标准库。下表显示了支持 .NET 标准库的整套 .NET 运行时。

平台名称Alias        
.NET Standardnetstandard1.01.11.21.31.41.51.62.0
.NET 核心netcoreapp1.0vNext
.NET Frameworknet4.54.5.14.64.6.14.6.2vNext4.6.1
Mono/Xamarin 平台
vNext
通用 Windows 平台uap10.0vNext
Windowswin8.08.1




Windows Phonewpa8.1




Windows Phone Silverlightwp8.0






注意,如果项目是面向多目标框架的,那么引用类库时,被引用类库也要支持面向多目标框架。

5. 单元测试

如果是使用.NET Framework类库项目来存放单元测试代码,那么可能会遇到一点问题。在VS2017 RC中,测试资源管理器无法识别出这些测试单元。通过新建“单元测试项目(.NET Framework)”,将生成的同名*.csproj覆盖原来的项目文件,测试管理器即可识别出来。


2.png

5. MSBuild自动编译新的解决方案

Windows下,按Release配置对整个解决方案编译。

"c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" XXX.sln /p:Configuration=Release;Platform="Any CPU"

会在相关类库根目录下\bin\Release目录中,生成net46和netstandard1.6两个目录。

6. 使用dotnet-nuget-push发布包

使用vs2017打包时,只需右击要打包的项目,选择“打包”,即可在.\bin\Debug或.\bin\Release下生成XXX.0[.0].0.nupkg文件,然后将这个文件.nupkg上传至nuget.org中。通过调用dotnet-nuget-push可以自动化这个发布过程,因此这种方式会更加方便。

dotnet nuget push XXX.0[.0].0.nupkg -k 4003d786-0000-4004-bfdf-c4f3e8ef9b3a -s http://customsource/

k:服务器的 API 密钥 s:服务器 URL,如发布到nuget.org,则可以这样写。

dotnet nuget push XXX.0[.0].0.nupkg -k 4003d786-0000-4004-bfdf-c4f3e8ef9b3a -s https://www.nuget.org/api/v2/package

通常在windows下,会将dotnet-nuget-push写在批处理文件中来完成基本类库的部署工作。

总结

通过此方案迁移后,最终保留新的解决方案和项目文件,旧的解决方案和项目文件在移植的过程中被删除。之后将按照新的解决方案来跨平台开发。基本类库的移植工作就介绍到这里。源代码的移植将是个挑战。譬如部分源码所引用的API在.NET Core框架下不存在时如何处理?另外,基础服务和Web Mvc项目的移植,因为要部署到linux中。也将会遇到各种问题。

参考资源

1. 组织项目以支持 .NET Framework 和 .NET Core

2. dotnet-nuget-push

3. packagesearch.azurewebsites.net

4. .NET 标准库

5. Developing Libraries with Cross Platform Tools

6. Target Frameworks

7. Porting to .NET Core from .NET Framework


本文责任编辑: 加入会员收藏夹 点此参与评论>>
复制本网址-发给QQ/微信上的朋友
AI智能听书
选取音色