11using Microsoft . Extensions . DependencyInjection ;
2+ using Microsoft . Extensions . Logging ;
23
34namespace AutomationPipelines ;
45
56/// <summary>
67/// Represents a pipeline of nodes.
78/// </summary>
8- public class Pipeline < TState > ( IServiceProvider serviceProvider ) : PipelineNode < TState > , IPipeline < TState >
9+ public class Pipeline < TState > : PipelineNode < TState > , IPipeline < TState >
910{
1011 private readonly List < IPipelineNode < TState > > _nodes = new ( ) ;
12+ private ILogger < Pipeline < TState > > ? _logger ;
1113
1214 private bool _callActionDistinct = true ;
1315 private Action < TState > ? _action ;
1416 private IDisposable ? _subscription ;
17+ private readonly IServiceProvider _serviceProvider ;
18+
19+ /// <inheritdoc />
20+ public Pipeline ( IServiceProvider serviceProvider )
21+ {
22+ _serviceProvider = serviceProvider ;
23+ }
24+
25+ /// <inheritdoc />
26+ public Pipeline ( IServiceProvider serviceProvider , ILogger < Pipeline < TState > > ? logger )
27+ {
28+ _serviceProvider = serviceProvider ;
29+ _logger = logger ;
30+ }
1531
1632 /// <inheritdoc />
1733 public IPipeline < TState > SetDefault ( TState state )
1834 {
1935 Input = state ;
36+ _logger ? . LogDebug ( $ "Default value set to { state } .") ;
2037 return this ;
2138 }
2239
2340 /// <inheritdoc />
2441 public IPipeline < TState > RegisterNode < TNode > ( ) where TNode : IPipelineNode < TState >
2542 {
26- return RegisterNode ( ActivatorUtilities . CreateInstance < TNode > ( serviceProvider ) ) ;
43+ return RegisterNode ( ActivatorUtilities . CreateInstance < TNode > ( _serviceProvider ) ) ;
2744 }
2845
2946 /// <inheritdoc />
@@ -35,13 +52,19 @@ public IPipeline<TState> RegisterNode<TNode>(TNode node) where TNode : IPipeline
3552 if ( _nodes . Any ( ) )
3653 {
3754 var previousNode = _nodes . Last ( ) ;
38- previousNode . OnNewOutput . Subscribe ( output => node . Input = output ) ;
55+ previousNode . OnNewOutput . Subscribe ( output =>
56+ {
57+ node . Input = output ;
58+ _logger ? . LogTrace ( $ "Node { previousNode } passed value { output } to node { node } .") ;
59+ } ) ;
3960
4061 node . Input = previousNode . Output ;
4162 }
4263
4364 _nodes . Add ( node ) ;
4465
66+ _logger ? . LogDebug ( $ "Node { node } registered.") ;
67+
4568 if ( _nodes . Count == 1 )
4669 {
4770 node . Input = Input ;
@@ -55,6 +78,10 @@ public IPipeline<TState> RegisterNode<TNode>(TNode node) where TNode : IPipeline
5578 /// <inheritdoc />
5679 public IPipeline < TState > SetOutputHandler ( Action < TState > action , bool callActionDistinct = true )
5780 {
81+ _logger ? . LogDebug ( callActionDistinct
82+ ? "Setting output handler."
83+ : "Setting output handler. Action calls with duplicate values are allowed." ) ;
84+
5885 _callActionDistinct = callActionDistinct ;
5986 _action = action ;
6087 if ( Output != null )
@@ -68,25 +95,40 @@ public IPipeline<TState> SetOutputHandler(Action<TState> action, bool callAction
6895 /// <inheritdoc />
6996 protected override void InputReceived ( TState ? state )
7097 {
98+ _logger ? . LogDebug ( $ "Input set to { state } .") ;
7199 if ( ! _nodes . Any ( ) )
72100 {
101+ _logger ? . LogTrace ( $ "No nodes, calling action immediately with { state } .") ;
73102 SetOutputAndCallActionWhenApplicable ( Input ) ;
74103 return ;
75104 }
76105
77- _nodes . First ( ) . Input = Input ;
106+ var firstNode = _nodes . First ( ) ;
107+ _logger ? . LogTrace ( $ "Passing input { state } to first node { firstNode } .") ;
108+ firstNode . Input = Input ;
78109 }
79110
80111 private void SetOutputAndCallActionWhenApplicable ( TState ? output )
81112 {
82113 var outputChanged = ! EqualityComparer < TState > . Default . Equals ( Output , output ) ;
83114
84115 Output = output ;
116+ _logger ? . LogDebug ( $ "Pipeline output set to { output } .") ;
117+
118+ if ( output == null )
119+ {
120+ _logger ? . LogTrace ( "No action set to execute." ) ;
121+ return ;
122+ }
85123
86- if ( output != null && ( ! _callActionDistinct || outputChanged ) )
124+ if ( _callActionDistinct && ! outputChanged )
87125 {
88- // Note that _action will be called AFTER OnNewOutput.
89- _action ? . Invoke ( output ) ;
126+ _logger ? . LogTrace ( "No action executed as output has not changed." ) ;
127+ return ;
90128 }
129+
130+ // Note that _action will be called AFTER OnNewOutput.
131+ _action ? . Invoke ( output ) ;
132+ _logger ? . LogTrace ( $ "Action executed with value { output } .") ;
91133 }
92134}
0 commit comments