Composite
Namespace: DesignPatterns.Structural
Overview
Tree structures where leaves and composites share a node contract. The library catalogs parts at compile time and assembles single-root trees or multi-root forests at runtime.
Runtime
ICompositeNode<TSelf>— node contract with childrenICompositeBuildable<TNode>— receives assembled children viaSetChildrenCompositeCatalogAssembler.Assemble/AssembleForest— build from flat catalog entriesCompositeTraverser.Traverse/TraverseForest— depth-first (pre/post-order) and breadth-first traversalCompositeTreeBuilder<TNode>— manual tree construction
Source generator
Mark each implementation with [CompositePart] (generic on .NET 7+). The generator emits {Contract}CompositeKeys, {Contract}CompositeCatalog, BuildRoot(), and BuildForest().
csharp
[CompositePart<IMenuNode>("root")]
public sealed class HomeMenu : IMenuNode, ICompositeBuildable<IMenuNode> { ... }
[CompositePart<IMenuNode>("admin", Order = 5)]
public sealed class AdminMenu : IMenuNode, ICompositeBuildable<IMenuNode> { ... }
[CompositePart<IMenuNode>("settings", ParentKey = "root", Order = 10)]
public sealed class SettingsMenu : IMenuNode, ICompositeBuildable<IMenuNode> { ... }
var root = MenuNodeCompositeCatalog.BuildRoot(); // exactly one ParentKey == null
var forest = MenuNodeCompositeCatalog.BuildForest(); // one or more roots
CompositeTraverser.TraverseForest(forest, (node, depth, rootIndex) => { ... });| API | When to use |
|---|---|
BuildRoot() | Catalog has exactly one ParentKey == null entry |
BuildForest() | Catalog has one or more roots (ordered by Order, then key) |
Multi-root catalogs: BuildRoot() throws CompositeAssemblyException at runtime.
Diagnostics
DP010–DP015.
Sample
DesignPatterns.Samples.Composite — generated BuildForest() + TraverseForest, BuildRoot() failure on multi-root catalog, and manual CompositeTreeBuilder.
Maintainer doc: docs/Composite.md (中文).