GraphFoundation — 通用图基础框架

GraphFoundation --- 通用图基础框架

概述

GraphFoundation 是 WorkFlowPrj 的图数据结构基础框架,提供通用的图操作、事务管理、拓扑分析和快照机制。

核心特性

  • 存储外置:业务逻辑与存储解耦,支持内存、数据库等多种后端
  • 事务支持:命令模式实现可撤销事务,保证数据一致性
  • 事件驱动Rx.NET 实现的图变更事件流
  • 快照机制:不可变快照作为执行凭证,确保执行过程不受图变更影响
  • 拓扑分析:支持关键路径等图分析算法

框架架构

#mermaid-svg-bLPRM3TVrI2A5YIi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bLPRM3TVrI2A5YIi .error-icon{fill:#552222;}#mermaid-svg-bLPRM3TVrI2A5YIi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bLPRM3TVrI2A5YIi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bLPRM3TVrI2A5YIi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bLPRM3TVrI2A5YIi .marker.cross{stroke:#333333;}#mermaid-svg-bLPRM3TVrI2A5YIi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bLPRM3TVrI2A5YIi p{margin:0;}#mermaid-svg-bLPRM3TVrI2A5YIi g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-bLPRM3TVrI2A5YIi g.classGroup text .title{font-weight:bolder;}#mermaid-svg-bLPRM3TVrI2A5YIi .cluster-label text{fill:#333;}#mermaid-svg-bLPRM3TVrI2A5YIi .cluster-label span{color:#333;}#mermaid-svg-bLPRM3TVrI2A5YIi .cluster-label span p{background-color:transparent;}#mermaid-svg-bLPRM3TVrI2A5YIi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bLPRM3TVrI2A5YIi .cluster text{fill:#333;}#mermaid-svg-bLPRM3TVrI2A5YIi .cluster span{color:#333;}#mermaid-svg-bLPRM3TVrI2A5YIi .nodeLabel,#mermaid-svg-bLPRM3TVrI2A5YIi .edgeLabel{color:#131300;}#mermaid-svg-bLPRM3TVrI2A5YIi .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-bLPRM3TVrI2A5YIi .label text{fill:#131300;}#mermaid-svg-bLPRM3TVrI2A5YIi .labelBkg{background:#ECECFF;}#mermaid-svg-bLPRM3TVrI2A5YIi .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-bLPRM3TVrI2A5YIi .classTitle{font-weight:bolder;}#mermaid-svg-bLPRM3TVrI2A5YIi .node rect,#mermaid-svg-bLPRM3TVrI2A5YIi .node circle,#mermaid-svg-bLPRM3TVrI2A5YIi .node ellipse,#mermaid-svg-bLPRM3TVrI2A5YIi .node polygon,#mermaid-svg-bLPRM3TVrI2A5YIi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bLPRM3TVrI2A5YIi .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi g.clickable{cursor:pointer;}#mermaid-svg-bLPRM3TVrI2A5YIi g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-bLPRM3TVrI2A5YIi g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-bLPRM3TVrI2A5YIi .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-bLPRM3TVrI2A5YIi .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-bLPRM3TVrI2A5YIi .dashed-line{stroke-dasharray:3;}#mermaid-svg-bLPRM3TVrI2A5YIi .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-bLPRM3TVrI2A5YIi #compositionStart,#mermaid-svg-bLPRM3TVrI2A5YIi .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #compositionEnd,#mermaid-svg-bLPRM3TVrI2A5YIi .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #dependencyStart,#mermaid-svg-bLPRM3TVrI2A5YIi .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #dependencyStart,#mermaid-svg-bLPRM3TVrI2A5YIi .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #extensionStart,#mermaid-svg-bLPRM3TVrI2A5YIi .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #extensionEnd,#mermaid-svg-bLPRM3TVrI2A5YIi .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #aggregationStart,#mermaid-svg-bLPRM3TVrI2A5YIi .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #aggregationEnd,#mermaid-svg-bLPRM3TVrI2A5YIi .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #lollipopStart,#mermaid-svg-bLPRM3TVrI2A5YIi .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi #lollipopEnd,#mermaid-svg-bLPRM3TVrI2A5YIi .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bLPRM3TVrI2A5YIi .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-bLPRM3TVrI2A5YIi .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bLPRM3TVrI2A5YIi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bLPRM3TVrI2A5YIi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bLPRM3TVrI2A5YIi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} <<interface>>
IReadOnlyGraph
<<interface>>
IGraph
<<interface>>
ICoreGraph
<<class>>
GraphEvent
<<class>>
CoreGraph
<<class>>
Commands
<<interface>>
ITransaction
<<interface>>
IGraphStorage
<<class>>
InMemoryGraphStorage
<<class>>
TopologyEngine
<<class>>
OrchestrationSystem
<<class>>
GraphSnapshot

核心接口

IReadOnlyGraph --- 只读图接口

提供图的只读访问能力,是所有图操作的基础。

csharp 复制代码
public interface IReadOnlyGraph<TKey, TNodeData, TEdgeData>
{
    TNodeData? GetNodeData(TKey key);
    TEdgeData? GetEdgeData(string edgeId);
    IReadOnlyList<TKey> GetAllNodeKeys();
    IReadOnlyList<string> GetAllEdgeIds();
    IReadOnlyList<(TKey Source, TKey Target, string EdgeId, bool IsDirected, double Weight, TEdgeData Data)> GetOutgoingEdges(TKey source);
    IReadOnlyList<(TKey Source, TKey Target, string EdgeId, bool IsDirected, double Weight, TEdgeData Data)> GetIncomingEdges(TKey target);
    IObservable<GraphEvent> Events { get; }
}

IGraph --- 可写图接口

继承只读接口,添加图的修改能力和事务支持。

csharp 复制代码
public interface IGraph<TKey, TNodeData, TEdgeData> : IReadOnlyGraph<TKey, TNodeData, TEdgeData>
{
    ITransaction BeginTransaction();
    void AddNode(TKey key, TNodeData data, string? symbol = null);
    void RemoveNode(TKey key);
    void AddEdge(string edgeId, TKey source, TKey target, bool isDirected, TEdgeData? data, double weight = 1.0);
    void RemoveEdge(string edgeId);
}

接口汇总

接口 职责
IReadOnlyGraph 只读访问:节点/边查询、事件订阅
IGraph 读写访问:节点/边增删、事务管理
ICoreGraph 可释放的核心图接口
IGraphStorage 存储抽象:支持内存/数据库等后端

执行流程

事务执行流程

EventSubject IGraphStorage Command LockedTransaction CoreGraph 客户端 EventSubject IGraphStorage Command LockedTransaction CoreGraph 客户端 #mermaid-svg-s3BYMA9fPTXjjd04{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-s3BYMA9fPTXjjd04 .error-icon{fill:#552222;}#mermaid-svg-s3BYMA9fPTXjjd04 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-s3BYMA9fPTXjjd04 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-s3BYMA9fPTXjjd04 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-s3BYMA9fPTXjjd04 .marker.cross{stroke:#333333;}#mermaid-svg-s3BYMA9fPTXjjd04 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-s3BYMA9fPTXjjd04 p{margin:0;}#mermaid-svg-s3BYMA9fPTXjjd04 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-s3BYMA9fPTXjjd04 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-s3BYMA9fPTXjjd04 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-s3BYMA9fPTXjjd04 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-s3BYMA9fPTXjjd04 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-s3BYMA9fPTXjjd04 .sequenceNumber{fill:white;}#mermaid-svg-s3BYMA9fPTXjjd04 #sequencenumber{fill:#333;}#mermaid-svg-s3BYMA9fPTXjjd04 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-s3BYMA9fPTXjjd04 .messageText{fill:#333;stroke:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-s3BYMA9fPTXjjd04 .labelText,#mermaid-svg-s3BYMA9fPTXjjd04 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .loopText,#mermaid-svg-s3BYMA9fPTXjjd04 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-s3BYMA9fPTXjjd04 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-s3BYMA9fPTXjjd04 .noteText,#mermaid-svg-s3BYMA9fPTXjjd04 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-s3BYMA9fPTXjjd04 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-s3BYMA9fPTXjjd04 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-s3BYMA9fPTXjjd04 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-s3BYMA9fPTXjjd04 .actorPopupMenu{position:absolute;}#mermaid-svg-s3BYMA9fPTXjjd04 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-s3BYMA9fPTXjjd04 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-s3BYMA9fPTXjjd04 .actor-man circle,#mermaid-svg-s3BYMA9fPTXjjd04 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-s3BYMA9fPTXjjd04 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} loop 执行每个命令 BeginTransaction() 创建事务,获取写锁 Enqueue(command1) Enqueue(command2) Commit() Execute(context) 执行存储操作 记录待发布事件 发布事件 释放写锁 提交完成

命令模式架构

#mermaid-svg-ds5jsu3eSFeWBQRh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ds5jsu3eSFeWBQRh .error-icon{fill:#552222;}#mermaid-svg-ds5jsu3eSFeWBQRh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ds5jsu3eSFeWBQRh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ds5jsu3eSFeWBQRh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ds5jsu3eSFeWBQRh .marker.cross{stroke:#333333;}#mermaid-svg-ds5jsu3eSFeWBQRh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ds5jsu3eSFeWBQRh p{margin:0;}#mermaid-svg-ds5jsu3eSFeWBQRh g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-ds5jsu3eSFeWBQRh g.classGroup text .title{font-weight:bolder;}#mermaid-svg-ds5jsu3eSFeWBQRh .cluster-label text{fill:#333;}#mermaid-svg-ds5jsu3eSFeWBQRh .cluster-label span{color:#333;}#mermaid-svg-ds5jsu3eSFeWBQRh .cluster-label span p{background-color:transparent;}#mermaid-svg-ds5jsu3eSFeWBQRh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ds5jsu3eSFeWBQRh .cluster text{fill:#333;}#mermaid-svg-ds5jsu3eSFeWBQRh .cluster span{color:#333;}#mermaid-svg-ds5jsu3eSFeWBQRh .nodeLabel,#mermaid-svg-ds5jsu3eSFeWBQRh .edgeLabel{color:#131300;}#mermaid-svg-ds5jsu3eSFeWBQRh .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-ds5jsu3eSFeWBQRh .label text{fill:#131300;}#mermaid-svg-ds5jsu3eSFeWBQRh .labelBkg{background:#ECECFF;}#mermaid-svg-ds5jsu3eSFeWBQRh .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-ds5jsu3eSFeWBQRh .classTitle{font-weight:bolder;}#mermaid-svg-ds5jsu3eSFeWBQRh .node rect,#mermaid-svg-ds5jsu3eSFeWBQRh .node circle,#mermaid-svg-ds5jsu3eSFeWBQRh .node ellipse,#mermaid-svg-ds5jsu3eSFeWBQRh .node polygon,#mermaid-svg-ds5jsu3eSFeWBQRh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ds5jsu3eSFeWBQRh .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh g.clickable{cursor:pointer;}#mermaid-svg-ds5jsu3eSFeWBQRh g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-ds5jsu3eSFeWBQRh g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-ds5jsu3eSFeWBQRh .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-ds5jsu3eSFeWBQRh .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-ds5jsu3eSFeWBQRh .dashed-line{stroke-dasharray:3;}#mermaid-svg-ds5jsu3eSFeWBQRh .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-ds5jsu3eSFeWBQRh #compositionStart,#mermaid-svg-ds5jsu3eSFeWBQRh .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #compositionEnd,#mermaid-svg-ds5jsu3eSFeWBQRh .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #dependencyStart,#mermaid-svg-ds5jsu3eSFeWBQRh .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #dependencyStart,#mermaid-svg-ds5jsu3eSFeWBQRh .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #extensionStart,#mermaid-svg-ds5jsu3eSFeWBQRh .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #extensionEnd,#mermaid-svg-ds5jsu3eSFeWBQRh .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #aggregationStart,#mermaid-svg-ds5jsu3eSFeWBQRh .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #aggregationEnd,#mermaid-svg-ds5jsu3eSFeWBQRh .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #lollipopStart,#mermaid-svg-ds5jsu3eSFeWBQRh .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh #lollipopEnd,#mermaid-svg-ds5jsu3eSFeWBQRh .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-ds5jsu3eSFeWBQRh .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-ds5jsu3eSFeWBQRh .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ds5jsu3eSFeWBQRh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ds5jsu3eSFeWBQRh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ds5jsu3eSFeWBQRh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} <<interface>>
ICommand
+Execute(context)
+Undo(context)
<<abstract>>
CommandBase<TKey, TNodeData, TEdgeData>
+Execute(context)
+Undo(context)
AddNodeCommand<TKey, TNodeData, TEdgeData>
RemoveNodeCommand<TKey, TNodeData, TEdgeData>
UpdateNodeCommand<TKey, TNodeData, TEdgeData>
AddEdgeCommand<TKey, TNodeData, TEdgeData>
RemoveEdgeCommand<TKey, TNodeData, TEdgeData>

核心模块

CoreGraph --- 核心图实现

职责:纯业务逻辑层,事务、事件、编排由本层管理,存储委托给 IGraphStorage。

特性 实现方式
并发控制 ReaderWriterLockSlim
事件发布 Rx.NET Subject
事务管理 命令模式 + 锁定事务
错误处理 IErrorHandler 可注入

GraphSnapshot --- 不可变图快照

职责:作为执行凭证,创建后内容不会改变,确保执行过程不受图变更影响。

csharp 复制代码
public class GraphSnapshot<TKey, TNodeData, TEdgeData>
{
    public string SnapshotId { get; }
    public string GraphId { get; }
    public int Version { get; }
    public IReadOnlyDictionary<TKey, NodeDefinition<TKey, TNodeData>> Nodes { get; }
    public IReadOnlyList<EdgeDefinition<TKey>> Edges { get; }
    public DateTime CreatedAt { get; }

    public static GraphSnapshot<TKey, TNodeData, TEdgeData> CreateFrom(
        IReadOnlyGraph<TKey, TNodeData, TEdgeData> graph,
        string graphId = "graph", int version = 1);

    public bool Validate(out IReadOnlyList<string> errors);
}

TopologyEngine --- 拓扑引擎

职责:执行拓扑分析和转换,支持连接转换器链。

csharp 复制代码
public class TopologyEngine<TKey, TNodeData, TEdgeData>
{
    public void AddTransformer(IConnectionTransformer transformer);
    public void Execute();
}

OrchestrationSystem --- 编排系统

职责:协调图操作流程,支持多个编排步骤的有序执行。

csharp 复制代码
public class OrchestrationSystem<TKey, TNodeData, TEdgeData>
{
    public void AddStep(IOrchestrationStep step);
    public OrchestrationResult Execute();
}

文件结构

#mermaid-svg-gkTqGNm1smbgsU8Q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gkTqGNm1smbgsU8Q .error-icon{fill:#552222;}#mermaid-svg-gkTqGNm1smbgsU8Q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gkTqGNm1smbgsU8Q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gkTqGNm1smbgsU8Q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gkTqGNm1smbgsU8Q .marker.cross{stroke:#333333;}#mermaid-svg-gkTqGNm1smbgsU8Q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gkTqGNm1smbgsU8Q p{margin:0;}#mermaid-svg-gkTqGNm1smbgsU8Q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q .cluster-label text{fill:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q .cluster-label span{color:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q .cluster-label span p{background-color:transparent;}#mermaid-svg-gkTqGNm1smbgsU8Q .label text,#mermaid-svg-gkTqGNm1smbgsU8Q span{fill:#333;color:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q .node rect,#mermaid-svg-gkTqGNm1smbgsU8Q .node circle,#mermaid-svg-gkTqGNm1smbgsU8Q .node ellipse,#mermaid-svg-gkTqGNm1smbgsU8Q .node polygon,#mermaid-svg-gkTqGNm1smbgsU8Q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gkTqGNm1smbgsU8Q .rough-node .label text,#mermaid-svg-gkTqGNm1smbgsU8Q .node .label text,#mermaid-svg-gkTqGNm1smbgsU8Q .image-shape .label,#mermaid-svg-gkTqGNm1smbgsU8Q .icon-shape .label{text-anchor:middle;}#mermaid-svg-gkTqGNm1smbgsU8Q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gkTqGNm1smbgsU8Q .rough-node .label,#mermaid-svg-gkTqGNm1smbgsU8Q .node .label,#mermaid-svg-gkTqGNm1smbgsU8Q .image-shape .label,#mermaid-svg-gkTqGNm1smbgsU8Q .icon-shape .label{text-align:center;}#mermaid-svg-gkTqGNm1smbgsU8Q .node.clickable{cursor:pointer;}#mermaid-svg-gkTqGNm1smbgsU8Q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gkTqGNm1smbgsU8Q .arrowheadPath{fill:#333333;}#mermaid-svg-gkTqGNm1smbgsU8Q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gkTqGNm1smbgsU8Q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gkTqGNm1smbgsU8Q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gkTqGNm1smbgsU8Q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gkTqGNm1smbgsU8Q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gkTqGNm1smbgsU8Q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gkTqGNm1smbgsU8Q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gkTqGNm1smbgsU8Q .cluster text{fill:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q .cluster span{color:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gkTqGNm1smbgsU8Q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gkTqGNm1smbgsU8Q rect.text{fill:none;stroke-width:0;}#mermaid-svg-gkTqGNm1smbgsU8Q .icon-shape,#mermaid-svg-gkTqGNm1smbgsU8Q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gkTqGNm1smbgsU8Q .icon-shape p,#mermaid-svg-gkTqGNm1smbgsU8Q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gkTqGNm1smbgsU8Q .icon-shape .label rect,#mermaid-svg-gkTqGNm1smbgsU8Q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gkTqGNm1smbgsU8Q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gkTqGNm1smbgsU8Q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gkTqGNm1smbgsU8Q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} GraphFoundation/
GraphFoundation.csproj
Graph/
IGraph.cs
CoreGraph.cs
Commands.cs
ITransaction.cs
Chain/
Chain.cs
OrchestrationSystem.cs
Topology/
TopologyEngine.cs
CriticalPath.cs
Storage/
IGraphStorage.cs
InMemoryGraphStorage.cs
Snapshots/
GraphSnapshot.cs
GraphDiff.cs
Navigation/
GraphNavigationExtensions.cs

事件系统

框架使用 Rx.NET 实现事件驱动架构,所有图变更都会发布事件:

事件类型 触发时机
NodeAddedEvent 添加节点
NodeRemovedEvent 移除节点
NodeUpdatedEvent 更新节点
EdgeAddedEvent 添加边
EdgeRemovedEvent 移除边
EdgeUpdatedEvent 更新边

快速使用示例

创建图

csharp 复制代码
var graph = new CoreGraph<string, object, object>();
graph.AddNode("A", new { Label = "开始" }, "START");
graph.AddNode("B", new { Label = "处理" }, "PROCESS");
graph.AddNode("C", new { Label = "结束" }, "END");
graph.AddEdge("A->B", "A", "B", isDirected: true, data: null, weight: 1.0);
graph.AddEdge("B->C", "B", "C", isDirected: true, data: null, weight: 1.0);

使用事务

csharp 复制代码
using (var tx = graph.BeginTransaction())
{
    tx.Enqueue(new AddNodeCommand<string, object, object>("D", new { Label = "分支" }, "DECISION"));
    tx.Enqueue(new AddEdgeCommand<string, object, object>("B->D", "B", "D", true, null, 1.0));
    tx.Commit();
}

创建快照

csharp 复制代码
var snapshot = GraphSnapshot<string, object, object>.CreateFrom(graph, "workflow", version: 1);
bool isValid = snapshot.Validate(out var errors);

使用拓扑引擎

csharp 复制代码
var engine = new TopologyEngine<string, object, object>(graph);
engine.AddTransformer(new ConnectionValidationTransformer());
engine.Execute();

设计原则

  1. 存储外置:业务逻辑与存储解耦,支持多种后端实现
  2. 命令模式:所有变更操作封装为命令,支持事务和撤销
  3. 事件驱动:图变更通过事件发布,支持响应式编程
  4. 不可变快照:快照创建后不可变,确保执行一致性
  5. 零外部依赖:核心层仅依赖 .NET 基础类库和 Rx.NET

与现有代码的对应关系

现有代码 GraphFoundation 中的对应 说明
GraphProcess CoreGraph + GraphSnapshot 图处理和执行
WorkFlowMethod OrchestrationSystem + Chain 工作流编排和链式处理
GraphDiff Snapshots/GraphDiff 图差异比较
相关推荐
不一样的故事1262 小时前
军工行业合规与基础认知
数据结构·经验分享·算法
To_OC9 小时前
LC 15 三数之和:双指针不难,难的是把去重做对
javascript·算法·leetcode
胡萝卜术10 小时前
深度重构:Agent Skills——从 Prompt 工程到能力工程
javascript·架构·github
踏月的造梦星球11 小时前
DMDPC 学习:架构、部署、运维与调优
运维·数据库·学习·架构
韩楚风11 小时前
【参天引擎】事务生命周期 / MVCC / Undo / ACID / 分布式事务 功能域整体解析
数据库·分布式·mysql·架构·cantian
通问AI11 小时前
Apple Intelligence 国行备案深度技术解析:阿里千问如何被集成到苹果端侧AI架构
人工智能·架构
明航咨询—张老师11 小时前
软考软件评测师技术深度剖析:2026年考试改革后的知识体系与备考架构
大数据·架构
renhongxia112 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
研究员子楚13 小时前
GEO行业发展标准体系白皮书V2.0-第10卷 · 全球篇:跨国标准协同与全球品牌语义治理框架
数据库·人工智能·microsoft·架构·geo