The IOperate interface in the OpNode project provides a powerful mechanism for attaching operations to nodes in a tree structure. This creates a dynamic calculation system where operations can be performed on child nodes and automatically recalculated when dependencies change.
-
IOperate Interface
- Extends
IChangefor change tracking - Properties:
Symbol(string representation),Operate(PNode node)method - Allows operations to be attached to nodes
- Extends
-
IChange Interface
Changedproperty: tracks if operation needs recalculationChange(PNode node)method: marks operation as changedChangeFalse(PNode node)method: resets change flag
-
PNode Class
- Extends TreeNode to represent nodes in tree structure
- Contains
List<IOperate> operationsto store attached operations - Key properties: Name, Value (for data), ErrorString (for errors)
- Key methods:
AddOperation(IOperate operation): Attaches operation and executes itPerformOperations(): Executes all operations on the nodeHasChangedOperations(): Checks if any operations need recalculationOperationChanged(): Marks parent operations as needing recalculation
-
Operator Abstract Class
- Base implementation of IOperate
- Handles change tracking and propagation
- Implements the
Change()method to notify parent nodes
-
Sum Class (Example Implementation)
- Concrete implementation of Operator
- Performs summation of all child node values
- Stores result in parent node's Value property
- Includes error handling for overflow and parsing failures
- Node Creation: Create nodes with names and optional values
- Tree Building: Add child nodes to parent nodes using
AddChild() - Operation Assignment: Add operations to nodes using
AddOperation() - Automatic Calculation: Operations immediately execute when added
- Change Propagation: When child values change, parent operations are marked for recalculation
- Lazy Recalculation: Operations only recalculate when
HasChangedOperations()returns true
// Create a sum node
var sumNode = new PNode("sum", "");
// Add child nodes with values
var item1 = new PNode("item1", "25");
var item2 = new PNode("item2", "75");
sumNode.AddChild(item1);
sumNode.AddChild(item2);
// Add Sum operation - automatically calculates 25 + 75 = 100
sumNode.AddOperation(new Sum());
// sumNode.Value now contains "100"
// Change a child value
item1.Value = "50";
item1.OperationChanged(); // Notify parent that recalculation needed
// Recalculate
sumNode.PerformOperations(); // Now calculates 50 + 75 = 125- Operations only recalculate when
HasChangedOperations()returns true - Optimizes performance by avoiding unnecessary calculations
- Change tracking propagates up the tree hierarchy
- Operations can report errors via the
ErrorStringproperty - Sum operation handles overflow and parsing errors gracefully
- Failed operations don't crash the system
- Operations can be applied to nodes that themselves have operations
- Creates a hierarchical calculation system
- Child operations execute before parent operations
- New operations can be created by implementing IOperate
- Operations can have symbols/icons for UI representation
- Plugin-like architecture allows easy addition of new functionality
- Sum: Adds all child node values
- Multiply: Multiplies all child node values
- Divide: Divides child node values
- Subtract: Subtracts child node values
- Sin, Cos, Tan: Trigonometric operations
- Min, Max, Average: Statistical operations
The IOperate interface provides a foundation for building calculation engines that could be used in:
- Financial Modeling: Create spreadsheet-like calculation trees
- Engineering Calculations: Build complex formula dependencies
- Data Processing: Create ETL-like transformation pipelines
- Game Development: Build skill trees or stat calculation systems
- Business Rules: Implement complex business logic with dependencies
The working demonstration shows:
- ✅ Basic sum operation functionality
- ✅ Child node addition and value changes
- ✅ Automatic recalculation when dependencies change
- ✅ Tree structure visualization
- ✅ Change propagation system
- ✅ Error handling for invalid values
- ✅ Nested operation support (with some limitations)
- Better Change Tracking: More granular change detection
- Circular Dependency Detection: Prevent infinite calculation loops
- Expression Parsing: Allow formula-based operations
- Validation Framework: Type checking and constraint validation
- Persistence: Save/load operation trees from storage
- Performance Optimization: Parallel calculation for independent branches
This architecture demonstrates a well-designed plugin system that could be extended to support a wide variety of calculation and transformation operations.