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();
设计原则
- 存储外置:业务逻辑与存储解耦,支持多种后端实现
- 命令模式:所有变更操作封装为命令,支持事务和撤销
- 事件驱动:图变更通过事件发布,支持响应式编程
- 不可变快照:快照创建后不可变,确保执行一致性
- 零外部依赖:核心层仅依赖 .NET 基础类库和 Rx.NET
与现有代码的对应关系
| 现有代码 | GraphFoundation 中的对应 | 说明 |
|---|---|---|
GraphProcess |
CoreGraph + GraphSnapshot |
图处理和执行 |
WorkFlowMethod |
OrchestrationSystem + Chain |
工作流编排和链式处理 |
GraphDiff |
Snapshots/GraphDiff |
图差异比较 |