Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const enSidebar = [
{ text: 'Factory Registry', link: '/factory-registry' },
{ text: 'Decorator', link: '/decorator' },
{ text: 'Event Aggregator', link: '/event-aggregator' },
{ text: 'State transition table', link: '/state-transition-table' },
{ text: 'Dependency Injection', link: '/dependency-injection' },
],
},
Expand All @@ -44,6 +45,7 @@ const zhSidebar = [
{ text: 'Factory Registry', link: '/zh/factory-registry' },
{ text: 'Decorator', link: '/zh/decorator' },
{ text: 'Event Aggregator', link: '/zh/event-aggregator' },
{ text: 'State 转换表', link: '/zh/state-transition-table' },
{ text: '依赖注入', link: '/zh/dependency-injection' },
],
},
Expand Down
13 changes: 13 additions & 0 deletions docs/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ Help links in the IDE point to this page (`#dp###` anchors).

See also [Registry key conventions](./registry-key-conventions.md).

## State transition table (DP026–DP031) {#state-transition-table-dp026-dp031}

| ID | Severity | When |
|----|----------|------|
| **DP026** | Error | Duplicate `(from state, trigger)` edge |
| **DP027** | Error | `[Transition]` state value is not a declared enum member |
| **DP028** | Error | `[Transition]` trigger value is not a declared enum member |
| **DP029** | Error | `[StateMachine]` `Initial` is not a declared state enum member |
| **DP030** | Error | Holder class is not `static partial` |
| **DP031** | Info | State enum member never appears as a `[Transition]` source (terminal/reserved hint) |

See [State transition table](./state-transition-table.md).

## Code fixes

`DesignPatterns.CodeFixes` ships inside the **`Skymly.DesignPatterns`** meta package (`analyzers/dotnet/cs`). Selected diagnostics offer one-click fixes in the IDE (requires C# Workspaces):
Expand Down
1 change: 1 addition & 0 deletions docs/samples.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The main [DesignPatterns](https://github.com/Skymly/DesignPatterns) CI checks ou
| **DesignPatterns.Samples.EventAggregator** | `IEventAggregator` pub/sub |
| **DesignPatterns.Samples.GenerateSingleton** | `[GenerateSingleton]` |
| **DesignPatterns.Samples.DependencyInjection** | `RegisterDi` for Strategy / Factory / Handler |
| **DesignPatterns.Samples.State** | Manual `TransitionTableBuilder` + `[StateMachine]` order lifecycle |

## NuGet consumption

Expand Down
53 changes: 53 additions & 0 deletions docs/state-transition-table.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# State transition table

Namespace: `DesignPatterns.Behavioral`

## Overview

Model finite state graphs as **(current state, trigger) → next state**. Use a manual builder or compile-time `[StateMachine]` / `[Transition]` attributes to avoid hand-written `switch` blocks and catch invalid edges at build time.

This is **not** a full UML state-machine framework (no hierarchical states, history, persistence, or entry/exit action DSL).

## Runtime

- `ITransitionTable<TState, TTrigger>` — `TryTransition`, `GetAllowedTriggers`, `CanTransitionFrom`
- `TransitionTableBuilder<TState, TTrigger>` — `WithInitial`, `Add`, `Build`
- `Transition()` extension — throws `InvalidTransitionException` on invalid edges

`TState` and `TTrigger` must be **enums** (v1).

```csharp
var table = new TransitionTableBuilder<OrderStatus, OrderTrigger>()
.WithInitial(OrderStatus.Draft)
.Add(OrderStatus.Draft, OrderTrigger.Submit, OrderStatus.Submitted)
.Add(OrderStatus.Submitted, OrderTrigger.Pay, OrderStatus.Paid)
.Build();

table.TryTransition(OrderStatus.Draft, OrderTrigger.Submit, out var next);
```

## Source generator

1. Define separate **state** and **trigger** enums.
2. Declare a **static partial** holder class with `[StateMachine(typeof(TState), typeof(TTrigger), Initial = ...)]`.
3. Add one or more `[Transition(from, trigger, to)]` attributes on the holder.

```csharp
[StateMachine(typeof(OrderStatus), typeof(OrderTrigger), Initial = OrderStatus.Draft)]
[Transition(OrderStatus.Draft, OrderTrigger.Submit, OrderStatus.Submitted)]
[Transition(OrderStatus.Submitted, OrderTrigger.Pay, OrderStatus.Paid)]
public static partial class OrderMachine;

// Generated: OrderStatusTransitionTable.Instance
// Holder: OrderMachine.TryTransition(...), OrderMachine.InitialState
```

## Diagnostics

DP026–DP031 — duplicate edges, invalid enum members, invalid holder, isolated states. See [Diagnostics](./diagnostics.md#state-transition-table-dp026-dp031).

## Sample

[DesignPatterns.Samples.State](https://github.com/Skymly/DesignPatterns.Samples/tree/main/DesignPatterns.Samples.State)

Maintainer doc: [docs/StateTransitionTable.md](https://github.com/Skymly/DesignPatterns/blob/main/docs/StateTransitionTable.md) (中文).
2 changes: 1 addition & 1 deletion docs/strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ DP003–DP007 — duplicate keys, contract mismatch, unregistered types (DP006 +

## Sample

[DesignPatterns.Samples.Strategy](https://github.com/Skymly/DesignPatterns.Samples/tree/main/DesignPatterns.Samples.Strategy)
[DesignPatterns.Samples.Strategy](https://github.com/Skymly/DesignPatterns.Samples/tree/main/DesignPatterns.Samples.Strategy) — sync payment strategies plus async `IRefundProcessor` with `ExecuteAsync` (`RefundProcessors.cs`).

## DI

Expand Down
13 changes: 13 additions & 0 deletions docs/zh/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ IDE 帮助链接指向本页(`#dp###` 锚点)。

另见 [注册表 Key 命名约定](./registry-key-conventions.md)。

## State 转换表(DP026–DP031) {#state-转换表-dp026-dp031}

| ID | 级别 | 触发条件 |
|----|------|----------|
| **DP026** | Error | `(from state, trigger)` 边重复 |
| **DP027** | Error | `[Transition]` 的 state 非 enum 成员 |
| **DP028** | Error | trigger 非 enum 成员 |
| **DP029** | Error | `[StateMachine]` 的 `Initial` 非 state enum 成员 |
| **DP030** | Error | holder 不是 `static partial` class |
| **DP031** | Info | state enum 成员从未作为 `[Transition]` 的 from(终态提示) |

见 [State 转换表](./state-transition-table.md)。

## CodeFix

`DesignPatterns.CodeFixes` 随 **`Skymly.DesignPatterns`** 元包分发(`analyzers/dotnet/cs`)。下列诊断支持 IDE 一键修复(需 C# Workspaces):
Expand Down
1 change: 1 addition & 0 deletions docs/zh/samples.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dotnet run --project DesignPatterns.Samples.Strategy -c Release
| **DesignPatterns.Samples.EventAggregator** | 事件聚合器 |
| **DesignPatterns.Samples.GenerateSingleton** | `[GenerateSingleton]` |
| **DesignPatterns.Samples.DependencyInjection** | Strategy / Factory / Handler 的 `RegisterDi` |
| **DesignPatterns.Samples.State** | 手动 `TransitionTableBuilder` + `[StateMachine]` 订单生命周期 |

## NuGet 消费

Expand Down
55 changes: 55 additions & 0 deletions docs/zh/state-transition-table.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# State 转换表

命名空间:`DesignPatterns.Behavioral`

## 概览

用 **(当前状态, 触发器) → 下一状态** 描述有限状态图。可用手动 Builder,或用编译期 `[StateMachine]` / `[Transition]` 减少手写 `switch` 并在构建期发现非法边。

**不是**完整 UML 状态机框架(无层次状态、历史、持久化或 entry/exit 动作 DSL)。

## 运行时

- `ITransitionTable<TState, TTrigger>` — `TryTransition`、`GetAllowedTriggers`、`CanTransitionFrom`
- `TransitionTableBuilder<TState, TTrigger>` — `WithInitial`、`Add`、`Build`
- `Transition()` 扩展 — 非法边时抛 `InvalidTransitionException`

v1 要求 `TState`、`TTrigger` 均为 **enum**。

```csharp
var table = new TransitionTableBuilder<OrderStatus, OrderTrigger>()
.WithInitial(OrderStatus.Draft)
.Add(OrderStatus.Draft, OrderTrigger.Submit, OrderStatus.Submitted)
.Add(OrderStatus.Submitted, OrderTrigger.Pay, OrderStatus.Paid)
.Build();

table.TryTransition(OrderStatus.Draft, OrderTrigger.Submit, out var next);
```

## 源生成器

1. 分别定义 **state enum** 与 **trigger enum**。
2. 声明带 `[StateMachine(typeof(TState), typeof(TTrigger), Initial = ...)]` 的 **static partial** holder。
3. 在 holder 上标注一条或多条 `[Transition(from, trigger, to)]`。

```csharp
[StateMachine(typeof(OrderStatus), typeof(OrderTrigger), Initial = OrderStatus.Draft)]
[Transition(OrderStatus.Draft, OrderTrigger.Submit, OrderStatus.Submitted)]
[Transition(OrderStatus.Submitted, OrderTrigger.Pay, OrderStatus.Paid)]
public static partial class OrderMachine;

// 生成:OrderStatusTransitionTable.Instance
// holder:OrderMachine.TryTransition(...)、OrderMachine.InitialState
```

## 诊断

DP026–DP031 — 重复边、非法 enum 成员、非法 holder、孤立态等。见 [诊断](./diagnostics.md#state-转换表-dp026-dp031)。

## 示例

[DesignPatterns.Samples.State](https://github.com/Skymly/DesignPatterns.Samples/tree/main/DesignPatterns.Samples.State)

维护者文档:[docs/StateTransitionTable.md](https://github.com/Skymly/DesignPatterns/blob/main/docs/StateTransitionTable.md)

英文完整版:[State transition table](../state-transition-table.md)
2 changes: 1 addition & 1 deletion docs/zh/strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ DP003–DP007;字面量 key 见 [DP025](./diagnostics.md#注册表-key-dp025)

## 示例

[DesignPatterns.Samples.Strategy](https://github.com/Skymly/DesignPatterns.Samples/tree/main/DesignPatterns.Samples.Strategy)
[DesignPatterns.Samples.Strategy](https://github.com/Skymly/DesignPatterns.Samples/tree/main/DesignPatterns.Samples.Strategy) — 同步支付策略与异步 `IRefundProcessor`(`ExecuteAsync`,见 `RefundProcessors.cs`)。

## DI

Expand Down
Loading