[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"consumer-news-detail-999":3,"consumer-news-interaction-999":40,"consumer-news-related-999":43},{"detail":4,"item":35},{"card":5,"schemaVersion":22,"fields":23,"content":29},{"id":6,"kind":7,"targetType":8,"targetId":9,"subtype":7,"typeLabel":10,"title":11,"subtitle":12,"summary":13,"coverUrl":14,"badgeText":14,"href":15,"sourceName":12,"meta":16,"metrics":19,"tags":20,"resolved":21},"NEWS_ARTICLE:999","news","NEWS_ARTICLE",999,"资讯","Vane.Dispatch 1.0.0 发布：一个与容器、传输层零耦合的 .NET 服务分发引擎","博客园","Vane.Dispatch 1.0.0 发布：一个与容器、传输层零耦合的 .NET 服务分发引擎 它的前身，可以追溯到一个叫 Ndf 的项目。从那时算起，已经过去了十多年。今天，它以 Vane.Dispatch 1.0.0 的名字正式发布。 序：十年磨一剑 做后端的人大抵都绕不开同一个问题：如何把&","","\u002Fnews\u002F999",[17,18],"2026","软件开发",{},[18],true,"consumer-content-detail-v1",{"sourceName":12,"authorName":24,"categoryName":18,"summary":13,"description":13,"publishTime":25,"updateTime":26,"sourceUrl":27,"language":28},"风云","2026-09-07T18:39","2026-09-11T15:22:02","https:\u002F\u002Fwww.cnblogs.com\u002Fnetcasewqs\u002Fp\u002F22878935","中文",{"format":30,"policy":31,"normalized":21,"html":32,"text":33,"wordCount":34,"hasBody":21},"HTML","NEWS_CONTENT_V1","Vane.Dispatch 1.0.0 发布：一个与容器、传输层零耦合的 .NET 服务分发引擎\n\u003Cblockquote>\n \u003Cp>它的前身，可以追溯到一个叫 \u003Cstrong>Ndf\u003C\u002Fstrong> 的项目。从那时算起，已经过去了十多年。今天，它以 \u003Cstrong>Vane.Dispatch 1.0.0\u003C\u002Fstrong> 的名字正式发布。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2>序：十年磨一剑\u003C\u002Fh2>\n\u003Cp>做后端的人大抵都绕不开同一个问题：如何把\"一个调用请求\"干净地路由到\"一段业务代码\"，并且把参数绑定、校验、过滤、异常这些横切关注点从业务里剥离出来。\u003C\u002Fp>\n\u003Cp>十多年前，这个项目最早以 \u003Cstrong>Ndf\u003C\u002Fstrong> 的雏形出现，承载着同样的想法。中间几经搁置、重写，直到 .NET 跨入 \u003Ccode>net8.0\u003C\u002Fcode> \u002F \u003Ccode>net10.0\u003C\u002Fcode> 时代，AOT、裁剪、源生成成为 mainstream 诉求，那个老想法才终于找到了最贴合的形态。2026-09-06，\u003Ccode>Vane.Dispatch 1.0.0\u003C\u002Fcode> 作为首个正式开源版本发布（此前 Ndf 已在公司内部多个项目中长期生产使用）。\u003C\u002Fp>\n\u003Cp>本文基于仓库中的全部源码与文档（\u003Ccode>README\u003C\u002Fcode>、\u003Ccode>developer-guide.md\u003C\u002Fcode>、三个示例、33 个测试文件）写成，力求每一个结论都能在代码里落地。\u003C\u002Fp>\n\u003Ch2>它是什么\u003C\u002Fh2>\n\u003Cp>\u003Ccode>Vane.Dispatch\u003C\u002Fcode> 是一个\u003Cstrong>微内核\u003C\u002Fstrong>：按特性（\u003Ccode>[Route]\u003C\u002Fcode>）把调用路由到控制器操作，做模型绑定，跑过滤器管线，并基于接口生成代理。它只依赖一个最小的 \u003Ccode>ServiceResolver\u003C\u002Fcode> 委托，\u003Cstrong>与任何 DI 容器、任何通信层都零耦合\u003C\u002Fstrong>。\u003C\u002Fp>\n\u003Cblockquote>\n \u003Cp>你可以自带解析器（或任意 \u003Ccode>IServiceProvider\u003C\u002Fcode>）、自带控制器、自带线格式。库本体仅依赖 \u003Ccode>net8.0\u003C\u002Fcode> BCL，双目标 \u003Ccode>net8.0;net10.0\u003C\u002Fcode>，所有公开类型统一归属 \u003Ccode>Vane.Dispatch\u003C\u002Fcode> 命名空间。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>它的定位不是\"又一个 Web 框架\"，而是\u003Cstrong>对标 ASP.NET Core MVC 的语义，但不绑定 HTTP 的契约分发引擎\u003C\u002Fstrong>。这句话是理解整个库设计取舍的钥匙。\u003C\u002Fp>\n\u003Ch2>核心设计原则\u003C\u002Fh2>\n\u003Ctable>\n \u003Cthead>\n  \u003Ctr>\n   \u003Cth>原则\u003C\u002Fth>\n   \u003Cth>含义\u003C\u002Fth>\n  \u003C\u002Ftr>\n \u003C\u002Fthead>\n \u003Ctbody>\n  \u003Ctr>\n   \u003Ctd>容器无关\u003C\u002Ftd>\n   \u003Ctd>唯一耦合点是 \u003Ccode>ServiceResolver\u003C\u002Fcode> 委托；用任意 \u003Ccode>IServiceProvider\u003C\u002Fcode> 包一层即可，\u003Cstrong>无需引入额外容器\u003C\u002Fstrong>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>传输层无关\u003C\u002Ftd>\n   \u003Ctd>路由\u002F绑定\u002F过滤器\u002F格式化全部在内存里完成；HTTP、gRPC、二进制协议都只是\"把字节适配成 \u003Ccode>DispatchRequest\u003C\u002Fcode>\"的宿主\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>AOT 友好\u003C\u002Ftd>\n   \u003Ctd>\u003Ccode>IsAotCompatible\u003C\u002Fcode> \u002F \u003Ccode>IsTrimmable\u003C\u002Fcode> 已开启；反射入口均有 \u003Ccode>[RequiresUnreferencedCode]\u003C\u002Fcode> \u002F \u003Ccode>[RequiresDynamicCode]\u003C\u002Fcode> \u002F \u003Ccode>[DynamicallyAccessedMembers]\u003C\u002Fcode> 标注\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>同步快路径 + 按需异步\u003C\u002Ftd>\n   \u003Ctd>默认全同步、\u003Ccode>Task\u003C\u002Fcode> 无关的零分配快路径；仅在处理器真正做 I\u002FO 时切到 \u003Ccode>DispatchAsync\u003C\u002Fcode>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n \u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch2>五分钟跑通\u003C\u002Fh2>\n\u003Cpre>\u003Ccode>using Vane.Dispatch;\n\n[Route(\"math\")]\npublic class MathController\n{\n    public int Add(int a, int b) =&gt; a + b;\n    public int Square(int x) =&gt; x * x;\n}\n\n\u002F\u002F 极简解析器：仅作演示，不引入任何 DI 容器\nServiceResolver resolver = type =&gt;\n    type.GetConstructor(Type.EmptyTypes)?.Invoke(null)\n    ?? throw new MissingMethodException(type.FullName);\n\nvar engine = resolver\n    .BuildDispatchEngine()\n    .MapDispatchable&lt;MathController&gt;()\n    .Build();\n\nint sum = engine.Dispatch&lt;int&gt;(\"math\", \"Add\", new { a = 2, b = 3 });   \u002F\u002F 5\nint sq  = engine.Send&lt;MathController, int&gt;(\"Square\", 6);              \u002F\u002F 36\n\npublic interface IMath { int Square(int x); }\nvar proxy = engine.CreateProxy&lt;IMath&gt;();\nint px = proxy.Square(9);                                             \u002F\u002F 81\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>如果你已经有 \u003Ccode>IServiceProvider\u003C\u002Fcode>，直接 \u003Ccode>services.BuildDispatchEngine()\u003C\u002Fcode> —— BCL 适配器会把你的 provider 包成解析委托，无需引入 \u003Ccode>Vane.Container\u003C\u002Fcode>。\u003C\u002Fp>\n\u003Ch2>特性详解\u003C\u002Fh2>\n\u003Ch3>1. 特性路由（Attribute Routing）\u003C\u002Fh3>\n\u003Cp>类级 \u003Ccode>[Route]\u003C\u002Fcode> 同时承担三件事：\u003Cstrong>可分发声明 + 路由组名 + 默认自动绑定推断\u003C\u002Fstrong>（对标 MVC 的 \u003Ccode>Controller + [Route] + [ApiController]\u003C\u002Fcode>）。方法级 \u003Ccode>[Route]\u003C\u002Fcode> 是操作契约名 \u002F 别名。查表大小写不敏感，构建期做重复操作检测（fail-fast）。\u003Ccode>[NoAutoBind]\u003C\u002Fcode> 可在类级关闭自动绑定。\u003C\u002Fp>\n\u003Ch3>2. 模型绑定：六种来源一次看懂\u003C\u002Fh3>\n\u003Cp>\u003Ccode>[FromBody]\u003C\u002Fcode> \u002F \u003Ccode>[FromRoute]\u003C\u002Fcode> \u002F \u003Ccode>[FromHeader]\u003C\u002Fcode> \u002F \u003Ccode>[FromQuery]\u003C\u002Fcode> \u002F \u003Ccode>[FromServices]\u003C\u002Fcode>，外加具名参数与复杂对象递归绑定。\u003Ccode>[FromRoute]\u002F[FromHeader]\u002F[FromQuery]\u003C\u002Fcode> 严格\u003Cstrong>来源隔离\u003C\u002Fstrong>——\u003Ccode>[FromHeader]\u003C\u002Fcode> 即使路由值里存在同名键也不会命中。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>[Route(\"binder\")][NoAutoBind]\npublic sealed class BinderController\n{\n    public byte[] EchoBody([FromBody] byte[] data) =&gt; data;     \u002F\u002F BodyModelBinder\n    public string Service([FromServices] IGreeter dep) =&gt; dep.Greet(); \u002F\u002F ServicesModelBinder\n    public int QueryVal([FromQuery] int q) =&gt; q;                \u002F\u002F ValueProviderModelBinder\n    public int RouteVal([FromRoute] int id) =&gt; id;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>默认 \u003Ccode>[Route]\u003C\u002Fcode> 还按类型自动推断：复杂 DTO → \u003Ccode>Body\u003C\u002Fcode>、接口 → \u003Ccode>Services\u003C\u002Fcode>、简单类型 → \u003Ccode>Payload\u003C\u002Fcode>，无需逐个写 \u003Ccode>[From*]\u003C\u002Fcode>。\u003C\u002Fp>\n\u003Ch3>3. 过滤器管线（对标 MVC 三态 \u003Ccode>OnExecuted\u003C\u002Fcode>）\u003C\u002Fh3>\n\u003Cp>全局与操作级过滤器。\u003Ccode>OnExecuted\u003C\u002Fcode> 在\u003Cstrong>成功 \u002F 异常 \u002F 取消三种状态下恒运行\u003C\u002Fstrong>，上下文携带 \u003Ccode>Exception\u003C\u002Fcode> \u002F \u003Ccode>Canceled\u003C\u002Fcode> \u002F \u003Ccode>ExceptionHandled\u003C\u002Fcode>，与 MVC 的 \u003Ccode>OnActionExecuted\u003C\u002Fcode> 语义一致。\u003Ccode>IExceptionFilter\u003C\u002Fcode> 可置 \u003Ccode>ExceptionHandled\u003C\u002Fcode> 免除失败判定。\u003C\u002Fp>\n\u003Cp>内置 \u003Ccode>UseValidation()\u003C\u002Fcode> 一键启用 DataAnnotations 校验（含 \u003Ccode>IValidatableObject\u003C\u002Fcode>），错误聚合到统一 \u003Ccode>ModelState\u003C\u002Fcode> → 400。\u003Cstrong>默认零校验开销\u003C\u002Fstrong>：不装配就不介入。\u003C\u002Fp>\n\u003Ch3>4. 格式化器与接口代理\u003C\u002Fh3>\n\u003Cp>JSON、原始字节、扁平二进制三种内置输入\u002F输出格式，可插入 MessagePack 等自定义二进制协议。\u003C\u002Fp>\n\u003Cp>\u003Ccode>CreateProxy&lt;T&gt;()\u003C\u002Fcode> 把任意接口变成进程内强类型客户端，走同一套分发内核（路由\u002F绑定\u002F过滤器），热路径零反射。\u003C\u002Fp>\n\u003Ch3>5. 自由端点（Minimal API 风格）\u003C\u002Fh3>\n\u003Cp>\u003Ccode>Map\u003C\u002Fcode> \u002F \u003Ccode>MapGet\u003C\u002Fcode> \u002F \u003Ccode>MapPost\u003C\u002Fcode> \u002F \u003Ccode>Handle\u003C\u002Fcode> 注册委托端点，支持 \u003Ccode>{name}\u003C\u002Fcode> 路径段捕获：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>var engine = resolver.BuildDispatchEngine()\n    .MapGet(\"\u002Fping\", () =&gt; \"pong\")\n    .MapPost(\"\u002Fecho\", (string msg) =&gt; msg)\n    .Build();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>6. 异步与取消\u003C\u002Fh3>\n\u003Cp>\u003Ccode>DispatchAsync\u003C\u002Fcode> 复用同一同步内核（路由\u002F绑定\u002F同步过滤器原样同步），仅对 \u003Ccode>Task\u003C\u002Fcode> \u002F \u003Ccode>ValueTask\u003C\u002Fcode> 处理器 \u003Ccode>await\u003C\u002Fcode>，并注入 \u003Ccode>CancellationToken\u003C\u002Fcode>。令牌取消统一映射为 \u003Cstrong>499\u003C\u002Fstrong>（\u003Ccode>RequestCanceled\u003C\u002Fcode>）。\u003C\u002Fp>\n\u003Ch3>7. 错误模型\u003C\u002Fh3>\n\u003Cp>\u003Ccode>DispatchResponse\u003C\u002Fcode> 是唯一响应载体，内置 \u003Ccode>Ok(200)\u003C\u002Fcode> \u003Ccode>BadRequest(400)\u003C\u002Fcode> \u003Ccode>NotFound(404)\u003C\u002Fcode> \u003Ccode>RequestCanceled(499)\u003C\u002Fcode> \u003Ccode>InternalServerError(500)\u003C\u002Fcode>。\u003Ccode>ProblemDetails\u003C\u002Fcode>（RFC 7807）在成功时为 \u003Ccode>null\u003C\u002Fcode>（零分配），失败时惰性生成供跨进程\u002FHTTP 宿主序列化。\u003C\u002Fp>\n\u003Ch2>性能与 AOT\u003C\u002Fh2>\n\u003Cul>\n \u003Cli>路由表\u003Cstrong>预构建\u003C\u002Fstrong>，热路径分发用\u003Cstrong>表达式编译调用器\u003C\u002Fstrong>而非反射；同步路径目标零分配确定性延迟。\u003C\u002Fli>\n \u003Cli>值提供器 \u002F 绑定 \u002F 路由是纯 CPU + 内存操作，刻意保持同步——没有可重叠的阻塞点，套 \u003Ccode>async\u003C\u002Fcode> 只增加状态机成本。\u003C\u002Fli>\n \u003Cli>异步 invoker 惰性编译，纯同步应用不产生常驻异步委托成本。\u003C\u002Fli>\n \u003Cli>库开启 XML 文档注释且未抑制 \u003Ccode>CS1591\u003C\u002Fcode>，构建保持 \u003Cstrong>0 警告\u003C\u002Fstrong>（\u003Ccode>TreatWarningsAsErrors\u003C\u002Fcode> 已开）。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>对标 MVC，而不是复刻 HTTP\u003C\u002Fh2>\n\u003Cp>这是库里最值得说清的一点。作者没有把 MVC 搬过来，而是做了一份\u003Cstrong>克制的差异清单\u003C\u002Fstrong>（\u003Ccode>docs\u002FMVC-Dispatch-Gap-Plan.md\u003C\u002Fcode>）：\u003C\u002Fp>\n\u003Cul>\n \u003Cli>\u003Cstrong>不做\u003C\u002Fstrong>：\u003Ccode>[HttpGet]\u003C\u002Fcode>\u002F\u003Ccode>[HttpPost]\u003C\u002Fcode> 动词约束、内容协商、\u003Ccode>IActionResult\u003C\u002Fcode> 体系、鉴权\u002F资源\u002F结果三类过滤器、\u003Ccode>IFormFile\u003C\u002Fcode> 表单绑定、\u003Ccode>{id:int}\u003C\u002Fcode> 路由类型约束。\u003C\u002Fli>\n \u003Cli>\u003Cstrong>原因\u003C\u002Fstrong>：Vane 没有 HTTP，这些语义本就不存在；直接返回 POCO 反而是定位优势。\u003C\u002Fli>\n \u003Cli>\u003Cstrong>已等价具备\u003C\u002Fstrong>：\u003Ccode>[ApiController]\u003C\u002Fcode> 自动 400、\u003Ccode>UseValidation()\u003C\u002Fcode> 批量校验、\u003Ccode>IExceptionFilter\u003C\u002Fcode>、结构化 \u003Ccode>ProblemDetails\u003C\u002Fcode>。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\"对标是为了认知零障碍迁移，不是复刻 HTTP\"——这条原则贯穿了整个 API 设计。\u003C\u002Fp>\n\u003Ch2>零传输耦合的真实证据\u003C\u002Fh2>\n\u003Cp>\u003Ccode>examples\u002FVane.Dispatch.HttpExample\u003C\u002Fcode> 用 \u003Ccode>System.Net.HttpListener\u003C\u002Fcode>（仅 BCL）把 HTTP 请求适配成 \u003Ccode>DispatchRequest\u003C\u002Fcode>，再经同一引擎完成绑定 + 过滤 + 表达式编译调用，响应经 \u003Ccode>IOutputFormatter\u003C\u002Fcode> 序列化。整个宿主只有约 150 行，没有引用任何第三方 HTTP 框架——这就是\"传输层无关\"不是口号的证明。\u003C\u002Fp>\n\u003Ch2>起步与获取\u003C\u002Fh2>\n\u003Cpre>\u003Ccode>dotnet add package Vane.Dispatch\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre>\u003Ccode>dotnet build Vane.Dispatch.slnx -c Release\ndotnet test  tests\u002FVane.Dispatch.Tests -c Release\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul>\n \u003Cli>源码与文档：\u003Ccode>https:\u002F\u002Fgitee.com\u002Fnetcasewqs\u002Fvane-dispatch\u003C\u002Fcode>\u003C\u002Fli>\n \u003Cli>许可：MIT\u003C\u002Fli>\n \u003Cli>作者：wangqingsong\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>结语\u003C\u002Fh2>\n\u003Cp>从 Ndf 到 Vane.Dispatch，变的是运行时的形态，不变的是\"把分发逻辑做薄、做纯、做快\"的执念。1.0.0 只是起点——它现在对标 MVC 语义、拥抱 AOT，下一步是把这条微内核路线在更多传输层上跑起来。\u003C\u002Fp>\n\u003Cp>如果你也在做服务分发、RPC 网关、或想给一套老系统换一个轻量内核，欢迎试一试，也欢迎提 Issue。\u003C\u002Fp>","Vane.Dispatch 1.0.0 发布：一个与容器、传输层零耦合的 .NET 服务分发引擎 它的前身，可以追溯到一个叫 Ndf 的项目。从那时算起，已经过去了十多年。今天，它以 Vane.Dispatch 1.0.0 的名字正式发布。 序：十年磨一剑 做后端的人大抵都绕不开同一个问题：如何把\"一个调用请求\"干净地路由到\"一段业务代码\"，并且把参数绑定、校验、过滤、异常这些横切关注点从业务里剥离出来。 十多年前，这个项目最早以 Ndf 的雏形出现，承载着同样的想法。中间几经搁置、重写，直到 .NET 跨入 net8.0 \u002F net10.0 时代，AOT、裁剪、源生成成为 mainstream 诉求，那个老想法才终于找到了最贴合的形态。2026-09-06，Vane.Dispatch 1.0.0 作为首个正式开源版本发布（此前 Ndf 已在公司内部多个项目中长期生产使用）。 本文基于仓库中的全部源码与文档（README、developer-guide.md、三个示例、33 个测试文件）写成，力求每一个结论都能在代码里落地。 它是什么 Vane.Dispatch 是一个微内核：按特性（[Route]）把调用路由到控制器操作，做模型绑定，跑过滤器管线，并基于接口生成代理。它只依赖一个最小的 ServiceResolver 委托，与任何 DI 容器、任何通信层都零耦合。 你可以自带解析器（或任意 IServiceProvider）、自带控制器、自带线格式。库本体仅依赖 net8.0 BCL，双目标 net8.0;net10.0，所有公开类型统一归属 Vane.Dispatch 命名空间。 它的定位不是\"又一个 Web 框架\"，而是对标 ASP.NET Core MVC 的语义，但不绑定 HTTP 的契约分发引擎。这句话是理解整个库设计取舍的钥匙。 核心设计原则 原则 含义 容器无关 唯一耦合点是 ServiceResolver 委托；用任意 IServiceProvider 包一层即可，无需引入额外容器 传输层无关 路由\u002F绑定\u002F过滤器\u002F格式化全部在内存里完成；HTTP、gRPC、二进制协议都只是\"把字节适配成 DispatchRequest\"的宿主 AOT 友好 IsAotCompatible \u002F IsTrimmable 已开启；反射入口均有 [RequiresUnreferencedCode] \u002F [RequiresDynamicCode] \u002F [DynamicallyAccessedMembers] 标注 同步快路径 + 按需异步 默认全同步、Task 无关的零分配快路径；仅在处理器真正做 I\u002FO 时切到 DispatchAsync 五分钟跑通 using Vane.Dispatch; [Route(\"math\")] public class MathController { public int Add(int a, int b) => a + b; public int Square(int x) => x * x; } \u002F\u002F 极简解析器：仅作演示，不引入任何 DI 容器 ServiceResolver resolver = type => type.GetConstructor(Type.EmptyTypes)?.Invoke(null) ?? throw new MissingMethodException(type.FullName); var engine = resolver .BuildDispatchEngine() .MapDispatchable\u003CMathController>() .Build(); int sum = engine.Dispatch\u003Cint>(\"math\", \"Add\", new { a = 2, b = 3 }); \u002F\u002F 5 int sq = engine.Send\u003CMathController, int>(\"Square\", 6); \u002F\u002F 36 public interface IMath { int Square(int x); } var proxy = engine.CreateProxy\u003CIMath>(); int px = proxy.Square(9); \u002F\u002F 81 如果你已经有 IServiceProvider，直接 services.BuildDispatchEngine() —— BCL 适配器会把你的 provider 包成解析委托，无需引入 Vane.Container。 特性详解 1. 特性路由（Attribute Routing） 类级 [Route] 同时承担三件事：可分发声明 + 路由组名 + 默认自动绑定推断（对标 MVC 的 Controller + [Route] + [ApiController]）。方法级 [Route] 是操作契约名 \u002F 别名。查表大小写不敏感，构建期做重复操作检测（fail-fast）。[NoAutoBind] 可在类级关闭自动绑定。 2. 模型绑定：六种来源一次看懂 [FromBody] \u002F [FromRoute] \u002F [FromHeader] \u002F [FromQuery] \u002F [FromServices]，外加具名参数与复杂对象递归绑定。[FromRoute]\u002F[FromHeader]\u002F[FromQuery] 严格来源隔离——[FromHeader] 即使路由值里存在同名键也不会命中。 [Route(\"binder\")][NoAutoBind] public sealed class BinderController { public byte[] EchoBody([FromBody] byte[] data) => data; \u002F\u002F BodyModelBinder public string Service([FromServices] IGreeter dep) => dep.Greet(); \u002F\u002F ServicesModelBinder public int QueryVal([FromQuery] int q) => q; \u002F\u002F ValueProviderModelBinder public int RouteVal([FromRoute] int id) => id; } 默认 [Route] 还按类型自动推断：复杂 DTO → Body、接口 → Services、简单类型 → Payload，无需逐个写 [From*]。 3. 过滤器管线（对标 MVC 三态 OnExecuted） 全局与操作级过滤器。OnExecuted 在成功 \u002F 异常 \u002F 取消三种状态下恒运行，上下文携带 Exception \u002F Canceled \u002F ExceptionHandled，与 MVC 的 OnActionExecuted 语义一致。IExceptionFilter 可置 ExceptionHandled 免除失败判定。 内置 UseValidation() 一键启用 DataAnnotations 校验（含 IValidatableObject），错误聚合到统一 ModelState → 400。默认零校验开销：不装配就不介入。 4. 格式化器与接口代理 JSON、原始字节、扁平二进制三种内置输入\u002F输出格式，可插入 MessagePack 等自定义二进制协议。 CreateProxy\u003CT>() 把任意接口变成进程内强类型客户端，走同一套分发内核（路由\u002F绑定\u002F过滤器），热路径零反射。 5. 自由端点（Minimal API 风格） Map \u002F MapGet \u002F MapPost \u002F Handle 注册委托端点，支持 {name} 路径段捕获： var engine = resolver.BuildDispatchEngine() .MapGet(\"\u002Fping\", () => \"pong\") .MapPost(\"\u002Fecho\", (string msg) => msg) .Build(); 6. 异步与取消 DispatchAsync 复用同一同步内核（路由\u002F绑定\u002F同步过滤器原样同步），仅对 Task \u002F ValueTask 处理器 await，并注入 CancellationToken。令牌取消统一映射为 499（RequestCanceled）。 7. 错误模型 DispatchResponse 是唯一响应载体，内置 Ok(200) BadRequest(400) NotFound(404) RequestCanceled(499) InternalServerError(500)。ProblemDetails（RFC 7807）在成功时为 null（零分配），失败时惰性生成供跨进程\u002FHTTP 宿主序列化。 性能与 AOT 路由表预构建，热路径分发用表达式编译调用器而非反射；同步路径目标零分配确定性延迟。 值提供器 \u002F 绑定 \u002F 路由是纯 CPU + 内存操作，刻意保持同步——没有可重叠的阻塞点，套 async 只增加状态机成本。 异步 invoker 惰性编译，纯同步应用不产生常驻异步委托成本。 库开启 XML 文档注释且未抑制 CS1591，构建保持 0 警告（TreatWarningsAsErrors 已开）。 对标 MVC，而不是复刻 HTTP 这是库里最值得说清的一点。作者没有把 MVC 搬过来，而是做了一份克制的差异清单（docs\u002FMVC-Dispatch-Gap-Plan.md）： 不做：[HttpGet]\u002F[HttpPost] 动词约束、内容协商、IActionResult 体系、鉴权\u002F资源\u002F结果三类过滤器、IFormFile 表单绑定、{id:int} 路由类型约束。 原因：Vane 没有 HTTP，这些语义本就不存在；直接返回 POCO 反而是定位优势。 已等价具备：[ApiController] 自动 400、UseValidation() 批量校验、IExceptionFilter、结构化 ProblemDetails。 \"对标是为了认知零障碍迁移，不是复刻 HTTP\"——这条原则贯穿了整个 API 设计。 零传输耦合的真实证据 examples\u002FVane.Dispatch.HttpExample 用 System.Net.HttpListener（仅 BCL）把 HTTP 请求适配成 DispatchRequest，再经同一引擎完成绑定 + 过滤 + 表达式编译调用，响应经 IOutputFormatter 序列化。整个宿主只有约 150 行，没有引用任何第三方 HTTP 框架——这就是\"传输层无关\"不是口号的证明。 起步与获取 dotnet add package Vane.Dispatch dotnet build Vane.Dispatch.slnx -c Release dotnet test tests\u002FVane.Dispatch.Tests -c Release 源码与文档：https:\u002F\u002Fgitee.com\u002Fnetcasewqs\u002Fvane-dispatch 许可：MIT 作者：wangqingsong 结语 从 Ndf 到 Vane.Dispatch，变的是运行时的形态，不变的是\"把分发逻辑做薄、做纯、做快\"的执念。1.0.0 只是起点——它现在对标 MVC 语义、拥抱 AOT，下一步是把这条微内核路线在更多传输层上跑起来。 如果你也在做服务分发、RPC 网关、或想给一套老系统换一个轻量内核，欢迎试一试，也欢迎提 Issue。",4369,{"id":6,"kind":7,"title":11,"summary":13,"image":14,"href":15,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":39},"2026 · 软件开发","#2563eb","16 \u002F 10",[18],{"targetType":8,"targetId":9,"likedByMe":41,"likeCount":42,"commentCount":42,"contentLikeCount":42,"contentCommentCount":42,"sourceLikeCount":42,"sourceCommentCount":42},false,0,[44,51,57,64,71,78,84,91],{"id":45,"kind":7,"title":46,"summary":47,"image":48,"href":49,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":50},"NEWS_ARTICLE:927","HelloCrab - 短视频开源爬虫，仅供学习参考","HelloCrab 基于 Avalonia、Playwright、AI与 FFmpeg 的跨平台桌面采集器，支持9大平台，以及 Android、iOS、Browser 远程控制端。 Made By ChatGPT &amp; Vincent with ❤ 平台 是否接入 哔哩哔哩 ✅ 抖音 ✅ 快手","https:\u002F\u002Fwww.cnblogs.com\u002Fhupo376787\u002Fp\u002FScreenshot\u002FWindows.jpg","\u002Fnews\u002F927",[18],{"id":52,"kind":7,"title":53,"summary":54,"image":14,"href":55,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":56},"NEWS_ARTICLE:929",".NET 异常处理的\"暗门\"：代码里写满 catch，你依然能抓住它——从一个 AI Agent 运行时的源码说起","一个健壮的系统，必然到处都是有意的 catch；异常被消化不等于问题不存在。 观测与韧性，是一个硬币的两面——降级逻辑保证系统不崩，FirstChance 保证你能看见它为什么降级。","\u002Fnews\u002F929",[18],{"id":58,"kind":7,"title":59,"summary":60,"image":61,"href":62,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":63},"NEWS_ARTICLE:933","写给 C++ 工程师的 OpenClaw.NET 上手指南：用你熟悉的 C++ 思维，跑起一个生产级 AI Agent","它像一个「基于 boost.asio + REST 端点的常驻服务」——对外是 HTTP \u002F WebSocket \u002F 各 IM 的 webhook，对内跑着一个能调工具、读写记忆、跨渠道对话的 AI Agent——只不过协程不用你手写 promise_type，内存不用你管 new\u002Fdelete。","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F510\u002F202609\u002F510-20260905070811424-1837144874.jpg","\u002Fnews\u002F933",[18],{"id":65,"kind":7,"title":66,"summary":67,"image":68,"href":69,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":70},"NEWS_ARTICLE:952",".NET 11 RC1 发布：拿到\"准生证\"，生产环境可以上了！","从 Preview 1 到 RC1，.NET 11 的拼图基本完整了：Runtime Async 反超状态机模型、CoreCLR 登陆 WebAssembly、CLI 全面 NativeAOT 化（dotnet tool list 快 5.5 倍）、C# 15 补齐 union 和 labeled","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F510\u002F202609\u002F510-20260909153805786-850851443.png","\u002Fnews\u002F952",[18],{"id":72,"kind":7,"title":73,"summary":74,"image":75,"href":76,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":77},"NEWS_ARTICLE:961","从零搭建ELK日志采集系统：Filebeat + Logstash + ES + Kibana 保姆级教程","轻量级架构，一份配置全搞定 一、前言 你是不是还在用 tail -f 和 grep 在多台服务器上翻日志？系统一出问题，就要登录三五台机器，来回切换窗口，定位一个Bug耗时半小时。 ELK 是业界最成熟的日志集中管理方案。本文将带你用 Docker Compose 一键部署 Filebeat + L","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F1465907\u002F202609\u002F1465907-20260909162947190-195439361.png","\u002Fnews\u002F961",[18],{"id":79,"kind":7,"title":80,"summary":81,"image":61,"href":82,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":83},"NEWS_ARTICLE:980","写给 Rust 工程师的 OpenClaw.NET 上手指南：用你熟悉的 Rust 思维，跑起一个生产级 AI Agent","它像一个「axum 应用」——对外是 HTTP \u002F WebSocket \u002F 各 IM 的 webhook，对内跑着一个能调工具、读写记忆、跨渠道对话的 AI Agent——只不过 async 不用选 runtime，也不用和借用检查器格斗。","\u002Fnews\u002F980",[18],{"id":85,"kind":7,"title":86,"summary":87,"image":88,"href":89,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":90},"NEWS_ARTICLE:1002","从对标 Java 到对标 Go：Native AOT 的\"无痛化\"之路，走到哪一站了？","从 .NET 7 的 demo 到 .NET 12 的无痛化，这条路要走五年。慢吗？慢。但对比一下：Java 的 GraalVM Native Image 折腾了更久，至今 Spring 生态的 AOT 体验仍在打补丁；Go 则是天生就站在终点线上——.NET 是在背着二十年的反射遗产追赶一个轻装上","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F510\u002F202609\u002F510-20260907133134585-1733425989.png","\u002Fnews\u002F1002",[18],{"id":92,"kind":7,"title":93,"summary":94,"image":14,"href":95,"meta":36,"badge":10,"author":12,"stats":-1,"accent":37,"coverRatio":38,"tags":96},"NEWS_ARTICLE:1012","java 多线程开发系列之八：玩转多线程（线程的中断）","之前的线程协作，讲的是通过wait和notify方法，多线程之间进行互相条件唤醒的办法。除此之外我们还需要进行中断操作。等待和唤醒可参考前文https:\u002F\u002Fwww.cnblogs.com\u002Fjilodream\u002Fp\u002F22770136设想这样一个场景：长工在给地主家干活，日出而作，日落而息。思路很简单：","\u002Fnews\u002F1012",[18]]