从CLR 到framework 到 .net core 、 ASP.NET CORE

一曲冷凌霜 提交于 2020-12-19 05:04:23

从CLR 到framework 到 .net core 、 ASP.NET CORE

前言:

    总有人问我,.NET CORE 是不是跟.NET 有很大区别,有哪些哪些语法有什么不同 ,你要讲讲培训培训 ,要专门讲一堂课!!- -。
我心里想了一想,.net core 和.net framework 区别讲一堂课?臣妾做不到。。。因为简单的说可能就几句话, 后面仔细想了想,往细了说可能要从 语言和框架,还有底层相关知识说起。
    为了说得更清晰,我从 硬件 ——  机器语言—— CLR运行时(java叫虚拟机)—— Base Class Library(java的系统包,) —— 高级语言编写的程序 —— asp.net core  一步步来说这事!

1. 基础知识

a.硬件

硬件就没什么好说的了,CPU、内存、硬盘...

b. 机器语言———— 直接操作硬件 由于计算机内部只能接受二进制代码,因此,用二进制代码0和1描述的指令称为机器指令,全部机器指令的集合构成计算机的机器语言,用机器语言编程的程序称为目标程序。

  • 高级语言———— 计算机不能直接执行,必须经过转换或者解释才能执行, 相对于机器语言来说是高级语言。比如 C# 语言,是一种通用的类型安全且面向对象的高级编程语言。

c. CLR 公共语言运行时

是一个类似JAVA虚拟机的代码运行环境,结构如下 CLR 执行示意图 CLR 执行示意图

d.Base Class Library

基础类库、 ADO.NET 库、异常处理、线程、数据类型等等。。。

什么叫做framework 呢?

它定义是:一个多语言组件的开发和执行环境
也就是: CLR +Base Class Library 才是 framework

C# 高级编程语言,它只是 framework 支持的高级语言中的一种。

e. .NET CORE 和.NET Framework 的区别

  • .NET Standard

.NET Standard 是一套正式的 .NET API 规范,有望在所有 .NET 实现中推出。 推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。 ECMA 335 持续为 .NET 实现行为建立统一性,但适用于 .NET 库实现的 .NET 基类库 (BCL) 没有类似的规范。

  • 我们再来看 .NET Framework 和 .NET core ,他们两者都是开发和执行环境 都是是由自己的 CLR +Base Class Library 组成,都支持C# 。 只是 .NET CORE是跨平台的。

所以说两者的区别是: CLR 和 Base Class Library 不同。 也就是说我们编程使用的C# 语法不变,只是基础库的API变了,也就是一些基础命名控件,方法等变换。比如 我们常见的获取当前目录

我们以前经常用的是 System.AppDomain.CurrentDomain.BaseDirectory

.net core 需这么操作 Directory.GetCurrentDirectory()

还有引用方式,是nuget。

到此已经说明了.NET CORE和.NET Framework 的一部分区别了。


我相信大家认为他们有区别的原因是因为 asp.net core 这个基于.net core环境开发的web应用框架,接下的大部分篇幅我们来讲 asp.net core的关键知识点。

2. IOC控制反转

要说清楚IOC 得先说清一下几个概念 ——>

a. 依赖

比如说一台电脑必须需要有CPU、内存 也就是说电脑依赖于CPU、内存。 传统的依赖写法如下:

public class 笔记本PC
{
    public PC()
    {

    }

    public void StartButton()
    {
        IntelCPU cpu=new IntelCPU();
        cpu.Init();
        JSDMemory mm=new JSDMemory();
        mm.Init();
    }
}

public class IntelCPU
{
    public void Init()
    {}
}

public class JSDMemory
{
    public void Init()
    {}
}

可以看到PC类里固定(类型声明固定)了用 IntelCPU 对象模板(class)和JSDMemory 来创建 CPU和内存,映射到现实中就是 电脑主机上焊死了一个IntelCPU和金士顿内存,以后启动电脑都是固定的跑这两个硬件。 也就是说以后这电脑就是强依赖于焊死的这两个硬件了,要换就只能重新焊接(改代码)而且只能改换同样品牌的硬件。

b. 设计原则:依赖于抽象,而不是具体实现.

什么是抽象? 接口、抽象类。于是我们改造一下电脑的设计:

// 台式电脑
public class 台式PC
{
    private ICPU cpu;
    private IMemory memory;

    public void StartButton()
    {
        ICPU cpu=new IntelCPU();
        cpu.Init();
        IMemory mm=new JSDMemory();
        mm.Init();
    }
}
public interface ICPU
{
    void Init();
}

public class IntelCPU:ICPU
{
    public void Init()
    {}
}

public interface IMemory
{
    void Init();
}
public class JSDMemory:IMemory
{
    public void Init()
    {}
}

上述的代码就是依赖于抽象,通过ICPU和IntelCPU两个接口来减少了部分依赖,映射到现实就是 台式机新增了 CPU插座和内存插槽,可以更换任意品牌的CPU和内存。很明显的减少了依赖。

这代码还有点与现实不同的是———— 代码中的台式机 自己去创建的CPU和内存,这是相当于 电脑去控制 CPU和内存的制造,这个有点不实际,有点依赖于PC和内存两个类模板。

所以我们需要去掉这个电脑的“控制”能力 —— 控制反转。

c. IOC控制反转模式。 IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含常见设计模式中。 控制反转就是相当于把上文中的电脑自己去创建CPU的这个不合理的过程拿出来交给工厂。 电脑自己只保留一些注入的接口。 这个过程就是控制反转,把这个创建的过程转移了。

3. 依赖注入(DI)

第一条中我们说到,控制反转把依赖的 CPU对象和内存对象的创建转移到工厂(IOC容器可以看作特殊的工厂)里面去了。那我们电脑就成了如下代码形式了 ————

public class 台式PC
{
    private ICPU cpu;
    private IMemory memory;

    public void StartButton()
    {
        ICPU cpu=             ; // 只有引用缺少实例
        cpu.Init();
        IMemory mm=     ;
        mm.Init();
    }
}

CPU和内存缺少了一个创建过程。他不应该是是电脑自己创建,应该是由使用人拿来装进去。

也就是:你不应该自己创建它,而是应该由你的调用者给你.

人拿来cpu和内存装入的过程就可以理解为注入(DI)

如是我们把电脑改造一下,改成 “构造注入”,通过构造函数注入cpu和内存,也就是相当于我们装机的时候装好CPU和内存。

public class 台式PC
{
    private ICPU cpu;
    private IMemory memory;

    public 台式PC(ICPU cpuImp,IMemory memoryImp)
    {
        cpu=cpuImp;
        memory=memoryImp;
    }
    public void StartButton()
    {
        cpu.Init();
        mm.Init();
    }
}

以后我们需要换CPU或者内存的时候,就可以去JD买一个,拿回来重新注入了。

如果我们由100台电脑都要安装CPU和内存呢? 我们肯定就会安排一个专人来购买CPU来完成这个注入的过程。 我们需要统一管理———— IOC容器,它负责创建、销毁对象实例。你可以把它看成特殊的工厂是DI实现的方式。

4. ASP.NET CORE DI

在 .NET Core中DI的核心分为两个组件:IServiceCollection和 IServiceProvider。

  • IServiceCollection 负责注册,也就是先得告诉工厂我能创建哪些对象。
  • IServiceProvider 负责提供实例

IServiceCollection 接口三个方法定义是:

  • .AddTransient<ICPU, IntelCPU>() // 每一次GetService都会创建一个新的实例
  • .AddSingleton<ICPU, IntelCPU>() //整个应用程序生命周期以内只创建一个实例 ,单例
  • .AddScoped<ICPU, IntelCPU>(); // 每一个request级别只创建一个实例,同一个http request会在一个 scope内

ASP.NET Core可以在Startup.cs的 ConfigureService中配置DI 注册服务。

public void ConfigureServices(IServiceCollection services)
{
   services.AddTransient<ICPU,
     IntelCPU>();
   services.AddMvc();
)

controller 里获得对象——构造注入。

private ILoginService<ApplicationUser> _loginService;
public AccountController(
  ILoginService<ApplicationUser> loginService)
{
  _loginService = loginService;
}

5.中间件

中间件是组装到应用程序管道中以处理请求和响应的软件。 每个组件:

选择是否将请求传递给管道中的下一个组件。
可以在调用管道中的下一个组件之前和之后执行工作。
请求委托(Request delegates)用于构建请求管道,处理每个HTTP请求。

请求委托使用Run,Map和Use扩展方法进行配置。单独的请求委托可以以内联匿名方法(称为内联中间件)指定,或者可以在可重用的类中定义它。这些可重用的类和内联匿名方法是中间件或中间件组件。请求流程中的每个中间件组件都负责调用流水线中的下一个组件,如果适当,则负责链接短路。

将HTTP模块迁移到中间件解释了ASP.NET Core和以前版本(ASP.NET)中的请求管道之间的区别,并提供了更多的中间件示例。

使用 IApplicationBuilder 创建中间件管道
ASP.NET Core请求流程由一系列请求委托组成,如下图所示(执行流程遵循黑色箭头):

图片

每个委托可以在下一个委托之前和之后执行操作。委托还可以决定不将请求传递给下一个委托,这称为请求管道的短路。短路通常是可取的,因为它避免了不必要的工作。例如,静态文件中间件可以返回一个静态文件的请求,并使管道的其余部分短路。需要在管道早期调用异常处理委托,因此它们可以捕获后面管道的异常。

一、Run扩展方法

Run方法在说明上是这样的:在管道的尾端增加一个Middleware;它是执行的最后一个Middleware。即它执行完就不再执行下一个Middleware了。

二、Use扩展方法

Use方法,则是在管道中增加一个Middleware。如果调用了next.Invoke()方法,它会去执行下一个Middleware 。

三、Map与MapThen

Map比较不同,它将Middleware添加到管道中,它是在管道中增加了分枝。通过影射路径的方式,增加管道分枝。我们保留上面例子,并增加代码。

中间件更详细说明可以参考:

:https://www.cnblogs.com/stulzq/p/7760648.html

http://www.cnblogs.com/xiaoshou/p/5669122.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!