如何移植.NET Framework项目至.NET Core?
公司的项目一直采用.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会提示存在同名目录,所以创建时可以输入一个不同的名称,然后手工调整回来。
2. 编辑项目文件,使之支持面向多个目标框架。
通过VS2017 RC新建的项目,“类库(.Net Core)”或者“类库(.Net Standard)”,默认只有一个目标框架。我们可以编辑项目文件,使之支持面向多个目标框架。如支持目标框架为.NET Standard 1.4、.Net Core App 1.0和.NET Framework 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 Standard | netstandard | 1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 | 2.0 |
.NET 核心 | netcoreapp | → | → | → | → | → | → | 1.0 | vNext |
.NET Framework | net | → | 4.5 | 4.5.1 | 4.6 | 4.6.1 | 4.6.2 | vNext | 4.6.1 |
Mono/Xamarin 平台 | → | → | → | → | → | → | → | vNext | |
通用 Windows 平台 | uap | → | → | → | → | 10.0 | → | → | vNext |
Windows | win | → | 8.0 | 8.1 | |||||
Windows Phone | wpa | → | → | 8.1 | |||||
Windows Phone Silverlight | wp | 8.0 |
注意,如果项目是面向多目标框架的,那么引用类库时,被引用类库也要支持面向多目标框架。
5. 单元测试
如果是使用.NET Framework类库项目来存放单元测试代码,那么可能会遇到一点问题。在VS2017 RC中,测试资源管理器无法识别出这些测试单元。通过新建“单元测试项目(.NET Framework)”,将生成的同名*.csproj覆盖原来的项目文件,测试管理器即可识别出来。
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
3. packagesearch.azurewebsites.net
4. .NET 标准库
5. Developing Libraries with Cross Platform Tools
7. Porting to .NET Core from .NET Framework
如何移植.NET Framework项目至.NET Core?的更多相关文章
- NET Framework项目移植到NET Core上遇到的一系列坑(2)
目录 获取请求的参数 获取完整的请求路径 获取域名 编码 文件上传的保存方法 获取物理路径 返回Json属性大小写问题 webconfig的配置移植到appsettings.json 设置区域块MVC ...
- NET Framework项目移植到NET Core上遇到的一系列坑
原文:NET Framework项目移植到NET Core上遇到的一系列坑 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...
- NET Framework项目移植到NET Core上踩的坑(1)
本文章向大家介绍NET Framework项目移植到NET Core上遇到的一系列坑,主要包括NET Framework项目移植到NET Core上遇到的一系列坑使用实例.应用技巧.基本知识点总结和需 ...
- 将 Net 项目升级 Core项目经验:(一)迁移Net项目为Net Core\Standard项目
迁移Net项目为Net Core\Standard项目 背景: 我们公司内部有自己ORM开发框架,最新因为需要将系统迁移到国产服务器上,所以首先需要将最基础的ORM框架改造可以运行在国产服务器上.对于 ...
- [WPF]是时候将WPF控件库从.Net Framework升级到.NET Core 3.1
1. 升级到Core的好处 去年中我曾考虑将我的控件库项目Kino.Toolkit.Wpf升级到.NET Core,不过很快放弃了,因为当时.NET Core是预览版,编译WPF还需要使用最新的Vis ...
- 迁移WPF项目到.NET CORE
综述 .NET CORE 3.0开始,桌面端支持WPF了.很多.NET FRAMEWORK的项目已经跑了一阵子了,不是很有必要支持.NET CORE,不过最近用一个程序,为了贯彻一些C# 8的特性,需 ...
- .NET平台系列24:从.NET Framework迁移到.NET Core/.NET5的技术指南
系列目录 [已更新最新开发文章,点击查看详细] 本文讲解了在将代码从 .NET Framework 移植到 .NET(旧称为 .NET Core)时应考虑的事项. 对于许多项目,从 .NET ...
- .NET 4.5+项目迁移.NET Core的问题记录
.NET 4.5+项目迁移.NET Core的问题记录 这几天试着把目前的开发框架迁移到新的.net core平台,中间遇到的问题在这里简单记录一下. 迁移过程遇到的最大的问题IOC容器.我目前使用的 ...
- Orchard Core Framework:ASP.NET Core 模块化,多租户框架
Orchard Core Framework:ASP.NET Core 模块化,多租户框架 上一篇编写Orchard Core一分钟搭建ASP.NET Core CMS ,介绍ASP.NET Core ...
随机推荐
- select()/poll() 的内核实现
mark 引用:http://janfan.cn/chinese/2015/01/05/select-poll-impl-inside-the-kernel.html 文章 select()/poll ...
- RocketMQ-创建MappedFile本地文件
了解RocketMQ的都知道,它会保存所有的消息到本地文件.这个文件就是 MappedFile,每一个文件对应一个MappedFile.默认情况下大小位1g. 在MessageStoreConfig中 ...
- [Erlang]Erlang经常使用工具解说
原创文章,转载请注明出处:服务器非业余研究http://blog.csdn.net/erlib 作者Sunface 联系邮箱:cto@188.com 但凡有图形界面的都须要linux系统安装了wx图形 ...
- vue - check-versions.js for shell
shelljs:https://www.npmjs.com/package/shelljs , 类似linux.unix.powser shell里面的命令. ShellJS是Node.js API之 ...
- 【MVC5】对MySql数据库使用EntityFramework
版本: MySql : 5.6.3 MySql.Data : 6.9.7 MVC : 5 EntityFramework : 6.1.3 VS : 2015 步骤: 1.安装[mysql-connec ...
- JSP语法学习笔记
1.修改JSP页面模版:找到MyEclips安装目录,搜索“Jsp.vtl”,找到该文件修改编码,以及一些不需要用到的代码. 2.查找项目生成的Servlet文件路径:查看当前项目父级目录搜索 .me ...
- 我的Go语言学习之旅二:入门初体验 Hello World
好吧,全部的程序猿们都已经习惯了.学习不论什么一门语言,我们都会以Hello World实例開始我们的学习,我也不例外.先来一个简单的样例 打开编辑器 (能够用记事本,我已经习惯 Notepad++了 ...
- Codeforces 8D Two Friends 三分+二分+计算几何
题目链接:点击打开链接 题意:点击打开链接 三分house到shop的距离,二分这条斜边到cinema的距离 #include<stdio.h> #include<string.h& ...
- git 教程一
git 是一个开源的分布式版本控件系统,用于敏捷高效地处理任何或小或大的项目. Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件. Git 与常用 ...
- 安装应用程序 报“ 997 重叠 I/O 操作在进行中”错解决办法
解决办法: 原因: Per Microsoft's blog, patch KB2918614 appears to have caused installation issues 按照微软的博客,补 ...