将Asp.Net Core和corefx移植到.Net 4.0
引言
因为工作内容的原因需要兼容 XP,而 XP 最多支持到.Net Framework 4.0。因此无法享受到 .Net Core 带来的一堆很好用的库,好在无论 corefx 还是 Asp.Net Core 都是开源的,我们可以自行修改编译出支持 .Net 4.0 的版本。
技术可行性
Net 4.0 相比 4.5 和 netstandard 1.0,主要的差别有:
- System.Threading.Tasks.Task 类型。.Net 4.0 的 Task 没有 GetAwaiter 成员,编译器无法生成使用 async await 的代码。好在编译器查找 Task.GetAwaiter 并不是直接查找成员方法,如果是扩展方法也可以,那么我们通过对 Task 编写 GetAwaiter 扩展方法就可以在 .Net 4.0 中使用 async await 了。
- Reflection 类别的 API。.Net 4.5 对反射 API 进行了重构,分离出了 TypeInfo 用于运行时反射。在 .Net 4.0 中,我们可以自行编写一个 TypeInfo 类,但是 .Net 4.5 中 TypeInfo 继承自 Type。据我观察实现中 GetType 返回的对象实际上就是一个 TypeInfo 对象,这一点我们无法通过自己编写的 TypeInfo 做到,不过好在除了 mscorlib,其他库并没有用到这层继承关系,因此为了不产生问题我实现的 TypeInfo 没有继承自 Type。
- WeakReference<T>。.Net 4.5 中的 WeakReference<T> 并没有继承自 WeakReference,它的终结器方法是一个 InternalCall,也就是在 clr 中实现的。而我们无法修改 clr 的实现,因此我实现的 WeakReference<T> 继承自 WeakReference,重用了它的终结器。
- 其它一些类型中 API 的缺失。主要包括 GC、Cryptography。对于没有的类型,我们可以添加实现,但对于已存在的类型是没有办法进行修改的。虽然 clr 中有 TypeForwardTo,配合 assembly redirecting 技术可以替换类型的实现,但 .Net 4.0 编译的程序集默认引用了 mscorlib,而 mscorlib 并不能被 redirect,所以对于 mscorlib 中已存在类型的 API 缺失——这一点暂时没有办法解决。
已经移植的项目
corefx
- System.Runtime:添加了 ExceptionDispatchInfo、IReadOnlyCollection<T>等一些只读集合的接口、生成异步方法所需要的 AsyncStateMachineAttribute、以及使用 MVVM 中很常用的 CallerMemberNameAttribute 等
- System.AppContext:添加了 AppContext 类
- System.Runtime.CompilerServices.Unsafe:添加了 Unsafe 类(ref 和 指针转换、直接读写内存等)
- System.Threading:添加了 Volatile 类
- System.Threading.Tasks:添加支持 async await 相关的类
- System.Security.Cryptography.Algorithms:添加了 IncrementalHash 的实现
Asp.Net Core
- Microsoft.Extensions.DependencyInjection
- Microsoft.Extensions.Options
- Microsoft.Extensions.Configuration
这些写过 Asp,Net Core 的应该很熟悉,他们也可以用在普通的 .Net 桌面程序中
一些开源项目
- Autofac:一个功能很强大的 IoC 实现
- AutoMapper:对象间的映射
- MaterialDesignThemes:WPF 的 MaterialDesign
示例
- 新建一个 .Net 4.0 项目
- 在 Nuget 程序包源里加上 https://www.myget.org/F/dotnet40/api/v3/index.json,并将优先级调到最上面
- install-package System.Threading.Tasks -Version 4.3.0-net40(注意一定要加上 Version)
- 在 app.config 加上 assembly redirecting
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.12.0" newVersion="4.0.12.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.12.0" newVersion="4.0.12.0" />
</dependentAssembly>
- 然后你就可以愉快的 async await 了
下面的示例是使用了
Caliburn.Micro
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Configuration
Autofac
Autofac.Extensions.DependencyInjection
AutoMapper
AutoMapper.Extensions.Microsoft.DependencyInjection
public class AppBootstrapper : BootstrapperBase
{
public IConfiguration Configuration { get; }
public IServiceProvider ServiceProvider { get; private set; }
private IContainer _container; public AppBootstrapper()
{
Configuration = LoadConfiguration();
Initialize();
} private IConfiguration LoadConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json", false, false);
return builder.Build();
} protected override void Configure()
{
var serviceCollection = new ServiceCollection();
ServiceProvider = ConfigureServices(serviceCollection);
} public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddAutoMapper(AssemblySource.Instance.ToArray());
services.AddSingleton<IWindowManager>(new WindowManager());
services.AddSingleton<IEventAggregator>(new EventAggregator()); services.AddSingleton(p => _container); var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterAssemblyModules(AssemblySource.Instance.ToArray()); _container = builder.Build();
return new AutofacServiceProvider(_container);
}
}
看起来和在 Asp.Net Core 中没什么差别。
总结
虽然工作环境限制我们只能使用 .Net 4.0,但俗话说没有条件,创造条件也要上。将它们移植到 .Net 4.0 也是跟上 .Net Core 和开源的步伐的一种努力吧。
关于这些包和相关的版本号可以在 https://www.myget.org/feed/Packages/dotnet40 查看
关于移植到 .Net 4.0 的计划我创建了一个 github 组织,里面包含移植的所有项目 https://github.com/dotnet40/
最后,感谢大家花时间阅读!
将Asp.Net Core和corefx移植到.Net 4.0的更多相关文章
- Asp.Net Core 项目实战之权限管理系统(0) 无中生有
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- Asp.net Core的代码移植技巧,半天将SqlSugarORM转成Core
.net core中有哪些被抛弃的类 1.DataTable DataRow SqlDataAdapter DataRow DataColumn DataColumn 虽然这些类不是我ORM核心功能 ...
- ASP.NET Core 2.1 : 十.升级现有Core2.0 项目到2.1
.NET Core 2.1 终于发布了, 赶紧升级一下. 一. 安装SDK 首先现在并安装 SDK(64-bit) 安装完毕后如果新建项目可以看到已经有2.1的选项了 二. 更新现有2.0项目到2.1 ...
- 细说ASP.NET Core与OWIN的关系
前言 最近这段时间除了工作,所有的时间都是在移植我以前实现的一个Owin框架,相当移植到到Core的话肯定会有很多坑,这个大家都懂,以后几篇文章可能会围绕这个说下,暂时就叫<Dotnet Cor ...
- Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- Asp.Net Core 项目实战之权限管理系统(2) 功能及实体设计
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- Asp.Net Core 项目实战之权限管理系统(5) 用户登录
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
随机推荐
- linux--centos服务器配置
配置Centos服务器 1. 安装centos 安装时注意分区留下一个/data区给网站内容存储. 2. 配置网络连接 默认centos网络连接不是开机启动的,需要配置. vi /etc/sysc ...
- 纯css实现横向下拉菜单
自己最近在捣腾css代码,不光是js能做很多有趣的东西,这货也可以做很多东西,现在把自己的一些作品分享给大家. 做得有点粗糙,大家根据这个思路来,可以自己修改修改. 关于demo:这是一个横向下拉的菜 ...
- Analog/digital converter (ADC)
1.ADC1 and ADC2 are 10-bit successive approximation Anolog to Digital Converters. 所谓successive appro ...
- JVM高级特性-一、java内存结构区域介绍
区域划分: java虚拟机在执行程序的过程中,将内存分为功能不同的几个区域,如下图: 此图列出了内存划分的各个区域,其中 线程私有的:程序计数器.虚拟机栈.本地方法栈 线程共享的:堆.方法区 下面,逐 ...
- java io 流
Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- Web设计思想——渐进增强
最近在拜读一本Web体验相关的书<渐进增强--跨平台用户体验设计 >,阅读后做些总结,消化一下书中的精髓. 在阅读本文前,可以先思考下面几个问题. 1. 浏览网页的目的是什么? 2. 浏览 ...
- 深入理解 JavaScript 事件循环(一)— event loop
引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...
- jenkins跑maven项目的时候报错,看评论
Started by user admin Building in workspace /var/jenkins_home/workspace/helloworld [WS-CLEANUP] Dele ...
- echarts3 清空上一次加载的series数据
今天做图表的时候发现了一个问题,想和大家分享一下 我有一个下拉选框,每次选中都切换不同的数据,数据是从后台查询获取的,但是如果后台返回了数据每次渲染都没有问题,如果后台没有返回数据,但是我在渲染图表的 ...
- js中的匿名函数自执行
随笔,java中因为有修饰符的存在,那就有private类的存在,js不一样,没有修饰词一说,因此为了防止全局变量的污染,js中就出现了匿名函数,直接上code,看到的人可以自己体会: (functi ...