ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

OHIF 高级定制:深入解析 CustomizationService 的 inheritsFrom 继承与 transform 变换机制

OHIF 高级定制:深入解析 CustomizationService 的 inheritsFrom 继承与 transform 变换机制 OHIF 高级定制深入解析 CustomizationService 的 inheritsFrom 继承与 transform 变换机制【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers导读本指南聚焦 OHIF Viewer 定制系统中最具威力的两个高级特性inheritsFrom定制项继承与transform运行时变换函数。它们是构建基础通用定制 派生专用定制分层体系的两大支柱常用于上下文菜单、视口叠加层Viewport Overlay等场景的动态组装。读完本文你将掌握继承合并的执行顺序、浅合并的边界、嵌套继承与多层 transform 的调用链以及如何利用这些机制写出可维护、可复用的高级定制配置。高级定制机制概览在 OHIF 的 CustomizationService 中每个定制项customization都是一个以唯一 ID 为键的值对象。基础用法是通过$set、$push、$merge等 immutability-helper 命令修改某个定制而inheritsFrom与transform则定义了定制项之间的结构化关系与运行时行为inheritsFrom声明当前定制继承并合并另一个定制父定制的字段形成定制项的层级结构transform指定一个函数在运行时修改或增强定制对象通常用于执行附加初始化逻辑或以特殊方式组合字段。两者可组合使用构建父项继承字段 变换后返回最终结果的完整链路。完整的服务实现位于 CustomizationService.ts其类型定义见 types.ts。inheritsFrom定制项的继承机制作用inheritsFrom表示当前定制应继承并合并另一个定制的字段。系统获取父定制后合并其属性返回合并后的组合对象。工作原理从源码 transform() 方法 可以看到完整的执行逻辑当你请求或变换一个带有inheritsFrom: parentCustomizationId的定制时服务通过getCustomization(...)查找parentCustomizationId父定制的属性被复制进子定制但子定制自身的属性会覆盖父定制中同名的属性——合并通过Object.assign({}, parent, customization)完成是典型的浅合并如果子定制带有transform函数$transform它会在合并之后执行。const { inheritsFrom } customization; if (!inheritsFrom) { return customization; } const parent this.getCustomization(inheritsFrom); const result parent ? Object.assign({}, parent, customization) : customization; return result.$transform?.(this) || result;基础示例export default { measurementsContextMenu: { $set: { inheritsFrom: ohif.contextMenu, menus: [ { selector: ({ nearbyToolData }) !!nearbyToolData, items: [ // ... ], }, ], }, }, };这里measurementsContextMenu继承自ohif.contextMenu。在检索或变换时系统会将ohif.contextMenu合并进measurementsContextMenu。真实仓库中的实现印证上述示例并非虚构——它就是 test-extension 的 findingsContextMenu.ts 中真实存在的定制定义。该文件还展示了继承机制的另一种关键用法嵌套定制项的继承。{ id: siteSelectionSubMenu, selector: ({ nearbyToolData }) !!nearbyToolData, items: [ { inheritsFrom: ohif/contextMenuAnnotationCode, code: SCT:69536005, }, { inheritsFrom: ohif/contextMenuAnnotationCode, code: SCT:45048000, }, ], },在这里siteSelectionSubMenu中的每个菜单项都通过inheritsFrom: ohif/contextMenuAnnotationCode继承代码型菜单项的基础结构同时用自己的code如SCT:69536005覆盖具体取值。transform运行时变换函数作用transform指定一个函数可在运行时修改或增强定制对象常用于执行附加设置代码或以特殊方式组合字段。工作原理在定制对象内部定义transform(customizationService)函数系统检索定制时在合并完继承字段之后调用transform函数可以返回更新后的对象、克隆现有属性或对嵌套项应用逻辑。从源码可见transform通过$transform标记挂载在定制对象上在继承合并完成后立即执行// 继承合并完成后执行 $transform return result.$transform?.(this) || result;其中this指向合并后的定制对象本身详见 types.ts 中 TransformMarker 的说明customizationService则是注入的服务实例可用于在变换过程中查询其他已注册定制。示例export default { ohif/contextMenuAnnotationCode: { $transform: function (customizationService) { const { code: codeRef } this; if (!codeRef) { throw new Error(item ${this} has no code ref); } const codingValues customizationService.getCustomization(codingValues); const code codingValues[codeRef]; return { ...this, codeRef, code: { ref: codeRef, ...code }, label: this.label || code.text || codeRef, commands: [{ commandName: updateMeasurement }], }; }, }, };这段代码中transform函数从this中读取代码引用code reference在codingValues中查找该代码的更多数据在返回最终对象前将这些细节合并回this。注意一个细节当this中不存在codeRef时会主动抛出错误这体现了 transform 作为运行时校验与装配点的价值。组合示例ohif.contextMenu 的 transformcontextMenuCustomization.ts 展示了 transform 与继承结合使用的完整真实案例。ohif.contextMenu定制本身带有一个$transform函数它会克隆对象及子对象clonedObject与每个 menu 的浅拷贝避免修改原始定制对象遍历menus中的每个 menu将每个 item 交由customizationService.transform(item)处理。export default { ohif.contextMenu: { $transform: function (customizationService: CustomizationService) { const clonedObject { ...this }; clonedObject.menus this.menus.map(menu ({ ...menu })); for (const menu of clonedObject.menus) { const { items: originalItems } menu; menu.items []; for (const item of originalItems) { menu.items.push(customizationService.transform(item)); } } return clonedObject; }, }, };这意味着任何以inheritsFrom: ohif.contextMenu派生的上下文菜单其内部所有带有inheritsFrom如ohif/contextMenuAnnotationCode的菜单项都会逐层走一遍继承合并 transform 的流程从而实现代码型菜单项的自动装配。合并细节与执行顺序合并是浅合并根据源码实现继承合并采用Object.assign({}, parent, customization)即浅合并仅顶层字段被合并子定制同名属性覆盖父定制。若字段本身是嵌套对象或数组默认按引用共享不会做深拷贝。因此派生定制如需修改嵌套结构应在自身字段中整体替换或依赖 transform 函数进行克隆与重组如ohif.contextMenu的 transform 所做的那样。执行顺序固定若定义了transform它总是在继承解析之后运行支持嵌套多级继承每一级都可能带有自己的transform步骤变换结果会被缓存getCustomization会将最终变换后的值存入transformedCustomizations缓存避免每次请求都重复执行变换见 getCustomization 实现。当定制被修改setModeCustomization、setGlobalCustomization等或模式切换onModeEnter/onModeExit时会清空该缓存。视图层的消费方式以视口叠加层为例CustomizableViewportOverlay.tsx 中通过读取item.inheritsFrom来决定渲染哪个具体的 OverlayItem 组件const { inheritsFrom } item; const OverlayItemComponent OverlayItemComponents[inheritsFrom]; if (OverlayItemComponent) { return OverlayItemComponent {...overlayItemProps} /; }这说明inheritsFrom不仅是数据层面的字段合并引用还可以作为渲染层面的类型标识UI Type Customization被视图层用来选择对应的 React 组件。这正是源码注释中所说的Applies any inheritance due to UI Type customization.测试验证仓库中的单元测试 CustomizationService.test.js 覆盖了以下核心行为子定制通过inheritsFrom正确继承父定制的属性如label、color子定制自身的属性覆盖父定制同名属性父定制若带$transform子定制继承时同样会执行父的 transform 逻辑。常见使用场景基础定制与专用定制Base and Specialized Customizations使用inheritsFrom定义宽泛的通用定制例如通用上下文菜单ohif.contextMenu再创建仅覆盖某些字段的专用版本如measurementsContextMenu。test-extension 的 findingsContextMenu.ts 是这一模式的完整参考。动态组装Dynamic Assembly使用transform根据应用状态或其他已注册定制来计算或修改字段。典型如ohif/contextMenuAnnotationCode在运行时通过getCustomization(codingValues)查询编码值表动态组装菜单项的label、code与commands。嵌套项Nested Items定制内的某个项若也带有inheritsFrom将遵循相同的继承流程并可运行自己的transform逻辑。ohif.contextMenu的 transform 通过customizationService.transform(item)显式触发嵌套项的变换形成父 transform → 子继承 → 子 transform的链式处理。关键要点总结inheritsFrom是对另一个定制 ID 的引用若定义了transform它总是在继承解析完成后执行合并是浅合并子定制属性覆盖父定制同名属性嵌套对象/数组按引用共享可以嵌套多层继承每一级都可能带有自己的transform步骤变换结果会被缓存定制修改或模式切换时缓存失效并重新计算inheritsFrom同时可充当 UI 类型标识供视图层如CustomizableViewportOverlay选择渲染组件。【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表