摘要: 作为《ASP.NET Core 3框架揭秘》的升级版,《ASP.NET Core 6框架揭秘》提供了很多新的章节,同时对现有的内容进行大量的修改。虽然本书旨在对ASP.NET Core框架的架构设计和实现原理进行剖析,但是其中提供的258个实例演示却可以作为入门材料,这个系列会将这些演示实例单独提取 阅读全文
posted @ 2022-02-22 08:23 Artech 阅读(24045) 评论(8) 推荐(55) 编辑
摘要: 当我们使用System.Text.Json.JsonSerializer对一个字典对象进行序列化的时候,默认情况下字典的Key不能是一个自定义的类型,本文介绍几种解决方案。 阅读全文
posted @ 2024-03-19 08:33 Artech 阅读(1982) 评论(4) 推荐(14) 编辑
摘要: 毫不夸张地说,路由是ASP.NET Core最为核心的部分。路由的本质就是注册一系列终结点(Endpoint),每个终结点可以视为“路由模式”和“请求处理器”的组合,它们分别用来“选择”和“处理”请求。请求处理器通过RequestDelegate来表示,但是当我们在进行路由编程的时候,却可以使用任意类型的Delegate作为处理器器,这一切的背后是如何实现的呢? 阅读全文
posted @ 2024-03-18 11:51 Artech 阅读(2561) 评论(1) 推荐(19) 编辑
摘要: ASP.NET Core MVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。《设计篇》介绍了这种为“飞行中的飞机加油”的方案的实现原理?本篇我们将演示将介绍“分散定义Controller”的N种实现方案。源代码从这里下载。 阅读全文
posted @ 2024-03-06 08:56 Artech 阅读(3829) 评论(1) 推荐(18) 编辑
摘要: ASP.NET Core MVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。这种为“飞行中的飞机加油”的方案是如何实现的呢?该系列的两篇文章将关注于这个主题,本篇着重介绍“模块化”的总体设计,下篇我们将演示将介绍“分散定义Controller”的N种实现方案。 阅读全文
posted @ 2024-03-05 08:44 Artech 阅读(1931) 评论(6) 推荐(14) 编辑
摘要: ControllerModel类型的Actions属性包含一组描述有效Action方法的ActionModel对象。对于定义在Controller类型中的所有方法,究竟哪些方法才能成为有效的Action方法呢?所以在正式介绍ActionModel类型之前,我们先来聊聊Action方法的选择规则。 阅读全文
posted @ 2024-02-29 09:56 Artech 阅读(1453) 评论(2) 推荐(11) 编辑
摘要: 从编程的角度来看,一个MVC应用是由一系列Controller类型构建而成的,所以对于一个代表应用模型的ApplicationModel对象来说,它的核心就是Controllers属性返回的一组ControllerModel对象,每个ControllerModel对象是应用模型针对Controller类型的描述。 阅读全文
posted @ 2024-02-28 09:37 Artech 阅读(1432) 评论(1) 推荐(12) 编辑
摘要: 在对应用模型的基本构建方式具有大致的了解之后,我们来系统地认识一下描述应用模型的ApplicationModel类型。对于一个描述MVC应用模型的ApplicationModel对象来说,它承载的元数据绝大部分是由默认注册的DefaultApplicationModelProvider对象提供的,在接下来针对ApplicationModel及其相关类型(ControllerModel、ActionModel和ParameterModel等)的介绍中,我们还会着重介绍DefaultApplicationModelProvider对象采用怎样的方式提取并设置这些元数据。 阅读全文
posted @ 2024-02-27 08:25 Artech 阅读(567) 评论(2) 推荐(9) 编辑
摘要: 我个人觉得这是ASP.NET Core MVC框架体系最核心的部分。原因很简单,MVC框架建立在ASP.NET Core路由终结点上,它最终的目的就是将每个Action方法映射为一个或者多个路由终结点,路由终结点根据附加在Action上的若干元数据构建而成。为了构建描述当前应用所有Action的元数据,MVC框架会提取出定义在当前应用范围内的所有Controller类型,并进一步构建出基于Controller的应用模型。应用模型不仅仅是构建Action元数据的基础,承载API的应用还可以利用它自动生成API开发文档,一些工具甚至可以利用应用模型自动生成消费API的客户端代码。 阅读全文
posted @ 2024-02-26 08:14 Artech 阅读(1436) 评论(1) 推荐(14) 编辑
摘要: 我想很多人已经体验过GRPC提供的三种流式消息交换模式,在.NET Core上构建的GRPC应用本质上是采用HTTP2/HTTP3协议的ASP.NET Core应用,我们当然也可以在一个普通的ASP.NET Core应用实现这些流模式。不仅如此,HttpClient也提供了响应的支持,这篇文章通过一个简单的实例提供了相应的实现 阅读全文
posted @ 2024-02-20 08:13 Artech 阅读(1548) 评论(5) 推荐(12) 编辑
摘要: 针对“缓冲区”编程是一个非常注重“性能”的地方,我们应该尽可能地避免武断地创建字节数组来存储读取的内容,这样不但会导致大量的字节拷贝,临时创建的字节数组还会带来GC压力。要正确、高效地读写缓冲内容,我们应该对几个我们可能熟悉的类型具有更深的认识。 阅读全文
posted @ 2024-02-19 08:07 Artech 阅读(5515) 评论(8) 推荐(47) 编辑
摘要: 由于Memory存储的是单纯的二进制字节,所以原则上我们可以用来它作为媒介,在wasm模块和数组程序之间传递任何类型的数据。在JavaScript API中,Memory通过WebAssembly.Memory类型表示,我们一般将它内部的缓冲区映射相应类型的数组进行处理。WebAssembly也提供了相应的指令来提供针对Memory的读、写、扩容等操作 阅读全文
posted @ 2024-02-05 09:42 Artech 阅读(1472) 评论(4) 推荐(7) 编辑
摘要: WebAssembly程序总是以模块来组织,模块是基本的部署、加载和编译单元。在JavaScript编程接口中,模块通过WebAssembly.Module类型表示。WebAssembly.Module通过加载的.wasm二进制文件创建而成,它承载了描述wasm模块的元数据,类似于描述程序集的Assembly对象。WebAssembly.Module自身是只读且无状态的,有状态的是根据它结合指定的导入对象创建的模块实例,后者通过WebAssembly.Instance表示。这两个类型提供了几个核心API,解析我们就通过它们来介绍WebAssembly的这两个核心对象。 阅读全文
posted @ 2024-02-02 09:39 Artech 阅读(459) 评论(0) 推荐(3) 编辑
摘要: 对于绝大多数编程语言来说,类型都是编程的基础,WebAssembly自然也不例外。总的来说,WebAssembly涉及的类型不多,很好掌握,接下来我们就来介绍一下WebAssembly编程涉及到的几种类型。本篇内容参考WebAssembly Spec。 阅读全文
posted @ 2024-02-01 08:33 Artech 阅读(423) 评论(0) 推荐(4) 编辑
摘要: 当我们在一个Web应用中使用WebAssembly,最终的目的要么是执行wasm模块的入口程序(通过start指令指定的函数),要么是调用其导出的函数,这一切的前提需要创建一个通过WebAssembly.Instance对象表示的wasm模块实例(源代码)。 阅读全文
posted @ 2024-01-31 08:37 Artech 阅读(588) 评论(0) 推荐(5) 编辑
摘要: 利用WebAssembly的导入导出功能可以灵活地实现宿主JavaScript程序与加载的单个wasm模块之间的交互,那么如何在宿主程序与多个wasm之间传递和共享数据呢?这就需要使用到Global这个重要的对象了。 阅读全文
posted @ 2024-01-30 08:33 Artech 阅读(557) 评论(2) 推荐(8) 编辑
摘要: 在《WebAssembly入门笔记[2]》中,我们介绍了如何利用Memory在作为宿主的JavaScript应用和wasm模块之间传递数据,但是Memory面向单纯二进制字节的读写在使用起来还是不太方便,此时我们会更多地用到另一个重要的对象Table。Table利用用来存储一组指定类型的对象,说得准确一点是对象的引用,所以可以读取出来直接消费。 阅读全文
posted @ 2024-01-29 08:35 Artech 阅读(625) 评论(2) 推荐(6) 编辑
摘要: 利用灵活的“导入”和“导出”机制,WebAssembly与承载的JavaScript应用之间可以很便利地“互通有无”。《与JavaScript的交互》着重演示了如何利用函数的导入和导出实现功能的共享,接下来我们主要关注数据的传递或者共享。宗地来说,WebAssembly与宿主程序之间的数据传递主要有如下三种手段,本篇文章主要关注Memory。 阅读全文
posted @ 2024-01-26 08:40 Artech 阅读(759) 评论(0) 推荐(8) 编辑
摘要: 前一阵子利用Balazor开发了一个NuGet站点,对WebAssembly进行了初步的了解,觉得挺有意思。在接下来的一系列文章中,我们将通过实例演示的方式介绍WebAssembly的一些基本概念和编程模式。 阅读全文
posted @ 2024-01-25 08:27 Artech 阅读(1991) 评论(7) 推荐(15) 编辑
摘要: 前几天有人在我的《ASP.NET Core框架揭秘》读者群跟我留言说:“我最近在看ASP.NET Core MVC的源代码,发现整个系统太复杂,涉及的东西太多,完全找不到方向,你能不能按照《200行代码,7个对象——让你了解ASP.NET Core框架的本质》这篇文章思路剖析一下MVC框架”,今天我们就来试试看。 阅读全文
posted @ 2023-11-08 08:31 Artech 阅读(4424) 评论(33) 推荐(56) 编辑
摘要: 在过去一段时间里,我陆陆续续写一些关于.NET对象类型布局的文章,其中包括值类型和引用类型的内存布局、字符串对象和数组的内存布局等,这里作一个简单的汇总。 阅读全文
posted @ 2023-11-07 08:11 Artech 阅读(1676) 评论(4) 推荐(12) 编辑
摘要: 在《NativeBuffering,一种高性能、零内存分配的序列化解决方案[性能测试篇]》我比较了NativeBuffering和System.Text.Json两种序列化方式的性能,通过性能测试结果可以看出NativeBuffering具有非常明显的优势,有的方面的性能优势甚至是“碾压式”的,唯独针对字符串的序列化性能不够理想。我趁这个周末对此做了优化,解决了这块短板,接下来我们就来看看最新的性能测试结果和背后“加速”的原理。 阅读全文
posted @ 2023-11-06 08:29 Artech 阅读(1269) 评论(7) 推荐(13) 编辑
摘要: 实现一个极简的字节数组对象池 .NET利用ArrayPoolPool<T>和MemoryPool<T>提供了针对Array/Memory<T>的对象池功能。最近在一个项目中需要使用到针对字节数组的对象池,由于这些池化的字节数组相当庞大,我希望将它们分配到POH上以降低GC的压力。由于ArrayPoolPool<T>没法提供支持, 阅读全文
posted @ 2023-11-03 08:22 Artech 阅读(2106) 评论(5) 推荐(17) 编辑
摘要: 第一版的NativeBuffering([上篇]、[下篇])发布之后,我又对它作了多轮迭代,对性能作了较大的优化。比如确保所有类型的数据都是内存对齐的,内部采用了池化机器确保真正的“零内存分配”等。对于字典类型的数据成员,原来只是“表现得像个字段”,这次真正使用一段连续的内存构架了一个“哈希表”。我们知道对于每次.NET新版本的发布,原生的JSON序列化(System.Text.Json)的性能都作了相应的提升,本篇文章通过具体的性能测试比较NativeBuffering和它之间的性能差异。 阅读全文
posted @ 2023-11-02 09:46 Artech 阅读(2682) 评论(26) 推荐(20) 编辑
摘要: 两种基于时间窗口的限流器的简单实现 之前开发的一款基于OpenTelemetry的Tracing组件需要使用基于速率限制(Rate Limiting)的跟踪采样策略,本想使用现有的解决方案,比如System.Threading.RateLimiting命名空间下的RateLimiter。大体看了RateLimiter的三种实现(固定窗 阅读全文
posted @ 2023-11-01 08:29 Artech 阅读(1014) 评论(1) 推荐(7) 编辑
摘要: 《.NET中的数组在内存中如何布局? 》介绍了一个.NET下针对数组对象的内存布局。既然我们知道了内存布局,我们自然可以按照这个布局规则创建一段字节序列来表示一个数组对象。 阅读全文
posted @ 2023-10-31 08:44 Artech 阅读(807) 评论(6) 推荐(8) 编辑
摘要: 总的来说,.NET的值类型和引用类型都映射一段连续的内存片段。就内存布局来说,引用类型有两个独特的存在,一个是字符串,另一个就是数组。今天我们来聊聊数组类型的内存布局。 阅读全文
posted @ 2023-10-30 08:50 Artech 阅读(3462) 评论(5) 推荐(27) 编辑
摘要: 上文说到Unmanaged、BufferedBinary和BufferedString是NativeBuffering支持的三个基本数据类型,其实我们也可以说NativeBuffering只支持Unmanaged和IReadOnlyBufferedObject 阅读全文
posted @ 2023-08-01 08:30 Artech 阅读(1048) 评论(4) 推荐(6) 编辑
摘要: 之前一个项目涉及到针对海量(千万级)实时变化数据的计算,由于对性能要求非常高,我们不得不将参与计算的数据存放到内存中,并通过检测数据存储的变化实时更新内存的数据。存量的数据几乎耗用了上百G的内存,再加上它们在每个时刻都在不断地变化,所以每时每刻都无数的对象被创建出来(添加+修改),同时无数现有的对象被“废弃”(删除+修改)。这种情况针对GC的压力可想而知,所以每当进行一次2代GC的时候,计算的耗时总会出现“抖动”。为了解决这类问题,几天前尝试着创建了一个名为NativeBuffering的框架 阅读全文
posted @ 2023-07-31 08:31 Artech 阅读(2164) 评论(9) 推荐(22) 编辑
摘要: 作为构建.NET的标准,CLI Spec(ECMA-335)针对基元类型的对齐规则具有如下的描述。按照这个标准,我们是这么理解的:8字节的数据类型(int64、unsigned int64和float64)根据采用的机器指令架构选择4字节或者8字节对其。进一步来说,它们在x86/x64机器上的对其字节分别为4字节和8字节,但实验证明却并非如此。 阅读全文
posted @ 2023-07-18 08:24 Artech 阅读(801) 评论(1) 推荐(3) 编辑
摘要: 毫无疑问,字符串是我们使用频率最高的类型。但是如果我问大家一个问题:“一个字符串对象在内存中如何表示的?”,我相信绝大部分人回答不上来。我们今天就来讨论这个问题。 阅读全文
posted @ 2023-07-17 08:32 Artech 阅读(4522) 评论(11) 推荐(26) 编辑
摘要: 一个对象总是映射一块连续的内存序列(不考虑对象之间的引用关系),如果我们知道了引用类型实例的内存布局,以及变量引用指向的确切的地址,我们不仅可以采用纯“二进制”的方式在内存“绘制”一个指定引用类型的实例,还可以修改某个变量的“值”指向它 阅读全文
posted @ 2023-07-14 08:25 Artech 阅读(3128) 评论(4) 推荐(13) 编辑
摘要: 非公开的类型或者方法被“隐藏”在程序集内部,本就不希望从外部访问,但是有时候调用一个内部或者私有方法可能是唯一的“救命稻草”,这篇文章列出了几种具体的实现方式。 阅读全文
posted @ 2023-07-13 12:12 Artech 阅读(2904) 评论(1) 推荐(21) 编辑
摘要: C#具有一个默认开启的代码分析规则:[CA1810]Initialize reference type static fields inline,推荐我们以内联的方式初始化静态字段,而不是将初始化放在静态构造函数中。 阅读全文
posted @ 2023-07-10 08:36 Artech 阅读(2730) 评论(6) 推荐(16) 编辑
摘要: 现代化的应用及服务的部署场景主要体现在集群化、微服务和容器化,这一切都建立在针对部署应用或者服务的健康检查上。ASP.NET提供的健康检查不仅可能确定目标应用或者服务的可用性,还具有健康报告发布功能。ASP.NET框架的健康检查功能是通过HealthCheckMiddleware中间件完成的。我们不仅可以利用该中间件确定当前应用的可用性,还可以注册相应的IHealthCheck对象来完成针对不同方面的健康检查。 阅读全文
posted @ 2023-07-06 09:15 Artech 阅读(2705) 评论(5) 推荐(22) 编辑
摘要: 实例方法和静态方法有区别吗?对于很多人来说,这是一个愚蠢的问题。因为我们都知道它们的区别,实例方法作用于某个具体的上下文对象,该上下文对象可以利用this关键字获得;静态方法则是定义在某个类型中,不存在上下文对象的概念。但是如果我们从函数的角度来看的话,不论是静态方法还是实例方法都是一个用于处理输入参数的操作,貌似又没有什么区别。 阅读全文
posted @ 2023-07-05 08:33 Artech 阅读(4184) 评论(11) 推荐(24) 编辑
摘要: 同源策略是所有浏览器都必须遵循的一项安全原则,它的存在决定了浏览器在默认情况下无法对跨域请求的资源做进一步处理。为了实现跨域资源的共享,W3C制定了CORS规范。ASP.NET利用CorsMiddleware中间件提供了针对CORS规范的实现 阅读全文
posted @ 2023-07-04 08:43 Artech 阅读(1557) 评论(3) 推荐(10) 编辑
摘要: 除了参数,ref关键字还可以用在什么地方? 《老生常谈:值类型 V.S. 引用类型》中花了很大的篇幅介绍ref参数针对值类型和引用类型变量的传递。在C#中,除了方法的ref参数,我们还有很多使用ref关键字传递引用/地址的场景,本篇文章作一个简单的总结。 一、参数 二、数组索引 三、方法 四、ref 结构体 五、ref 结构体字段 一、参数 阅读全文
posted @ 2023-07-03 08:41 Artech 阅读(4184) 评论(9) 推荐(35) 编辑
摘要: 之前参与一个机票价格计算的项目,为他们设计了基本的处理流程,但是由于整个计算流程相当复杂,而且变化非常频繁,导致日常的修改、维护和升级也变得越来越麻烦,当我后来再接手的时候已经看不懂计算逻辑了。为了解决这个问题,我借鉴了“工作流”的思路,试图将整个计算过程设计成一个工作流。但是我又不想引入一个独立的工作流引擎,于是写了一个名为Pipelines的框架。 阅读全文
posted @ 2023-06-30 08:16 Artech 阅读(7553) 评论(35) 推荐(57) 编辑
摘要: 老生常谈:值类型 V.S. 引用类型 我在面试的时候经常会问一个问题:“谈谈值类型和引用的区别”。对于这个问题,绝大部分人都只会给我两个简洁的答案:“值类型分配在栈中,引用类型分配在堆中”,“在默认情况下,值类型参数传值(拷贝),引用类型参数传引用”。其实这个问题有很大的发挥空间,如果能够从内存布局、GC、互操作、跨AppDomain传 阅读全文
posted @ 2023-06-29 08:57 Artech 阅读(3919) 评论(10) 推荐(36) 编辑
摘要: ASP.NET应用并没有对如何定义授权策略做硬性规定,但是针对角色的授权策略依然是最常用的。角色(或者用户组)实际上就是对一组权限集的描述,将一个用户添加到某个角色之中就是为了将对应的权限赋予该用户。在《使用最简洁的代码实现登录、认证和注销》中,我们提供了一个用来演示登录、认证和注销的程序,现在我们在此基础上添加基于“角色授权的部分”。 阅读全文
posted @ 2023-06-25 09:43 Artech 阅读(3294) 评论(3) 推荐(13) 编辑