Skip to content

Commit 39ef092

Browse files
authored
Add Support for Anonymous Registration via PipelineBuilder (#24)
1 parent f55058e commit 39ef092

3 files changed

Lines changed: 58 additions & 33 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace PipeForge;
2+
3+
/// <summary>
4+
/// A pipeline step that delegates execution to a provided function.
5+
/// </summary>
6+
/// <typeparam name="TContext">The type of the pipeline context.</typeparam>
7+
internal sealed class DelegatePipelineStep<TContext> : PipelineStep<TContext>
8+
{
9+
private readonly Func<TContext, PipelineDelegate<TContext>, CancellationToken, Task> _invoke;
10+
11+
/// <summary>
12+
/// Initializes a new instance of the <see cref="DelegatePipelineStep{TContext}"/> class with a delegate to execute.
13+
/// </summary>
14+
/// <param name="invoke">The delegate to invoke during pipeline execution.</param>
15+
public DelegatePipelineStep(Func<TContext, PipelineDelegate<TContext>, CancellationToken, Task> invoke)
16+
{
17+
_invoke = invoke ?? throw new ArgumentNullException(nameof(invoke));
18+
}
19+
20+
public override Task InvokeAsync(TContext context, PipelineDelegate<TContext> next, CancellationToken cancellationToken = default)
21+
{
22+
return _invoke(context, next, cancellationToken);
23+
}
24+
}

src/PipeForge/Pipeline.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,6 @@ public static PipelineBuilder<T> CreateFor<T>() where T : class
3131
return new PipelineBuilder<T>();
3232
}
3333

34-
/// <summary>
35-
/// Creates a new instance of <see cref="PipelineBuilder{T}"/> for the specified context type.
36-
/// </summary>
37-
/// <remarks>
38-
/// This method is used to start building a pipeline for a specific type.
39-
/// It allows for fluent configuration of pipeline steps.
40-
/// </remarks>
41-
/// <typeparam name="T"></typeparam>
42-
/// <returns></returns>
43-
public static PipelineBuilder<T> CreateFor<T>(ILoggerFactory? loggerFactory) where T : class
44-
{
45-
return new PipelineBuilder<T>(loggerFactory);
46-
}
47-
4834
/// <summary>
4935
/// Discovers pipeline steps for a specific context type from all assemblies in the current AppDomain.
5036
/// </summary>

src/PipeForge/PipelineBuilder.cs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,68 @@
1-
using Microsoft.Extensions.Logging;
1+
using Microsoft.Extensions.DependencyInjection;
22

33
namespace PipeForge;
44

55
/// <summary>
66
/// PipelineBuilder is used to configure and build a pipeline of steps.
77
/// </summary>
8-
/// <typeparam name="T"></typeparam>
9-
public class PipelineBuilder<T>
10-
where T : class
8+
/// <typeparam name="TContext"></typeparam>
9+
public class PipelineBuilder<TContext>
10+
where TContext : class
1111
{
12-
private readonly List<Lazy<IPipelineStep<T>>> _steps = new();
13-
private readonly ILoggerFactory? _loggerFactory;
12+
private readonly IServiceCollection _services = new ServiceCollection();
1413

15-
internal PipelineBuilder() { }
14+
internal PipelineBuilder()
15+
{ }
1616

17-
internal PipelineBuilder(ILoggerFactory? loggerFactory)
17+
/// <summary>
18+
/// Builds a pipeline from the configured steps
19+
/// </summary>
20+
/// <returns></returns>
21+
public IPipelineRunner<TContext> Build()
1822
{
19-
_loggerFactory = loggerFactory;
23+
//return new PipelineRunner<TContext>(_services.BuildServiceProvider());
24+
throw new NotImplementedException();
2025
}
2126

2227
/// <summary>
23-
/// Builds a pipeline from the configured steps
28+
/// Configures the services used by the pipeline
2429
/// </summary>
30+
/// <param name="configure"></param>
2531
/// <returns></returns>
26-
public IPipelineRunner<T> Build()
32+
public PipelineBuilder<TContext> ConfigureServices(Action<IServiceCollection> configure)
2733
{
28-
return new PipelineRunner<T>(_steps, _loggerFactory);
34+
configure(_services);
35+
return this;
2936
}
3037

3138
/// <summary>
3239
/// Adds a step to the pipeline
3340
/// </summary>
3441
/// <typeparam name="TStep"></typeparam>
3542
/// <returns></returns>
36-
public PipelineBuilder<T> WithStep<TStep>() where TStep : IPipelineStep<T>, new()
43+
public PipelineBuilder<TContext> WithStep<TStep>() where TStep : class, IPipelineStep<TContext>
3744
{
38-
_steps.Add(new(() => new TStep()));
45+
_services.AddPipelineStep<TStep>();
3946
return this;
4047
}
4148

4249
/// <summary>
43-
/// Adds a step to the pipeline
50+
/// Adds a step to the pipeline using a delegate. By default, the step is registered with a transient lifetime.
51+
/// You can specify a different lifetime if needed.
4452
/// </summary>
45-
/// <typeparam name="TStep"></typeparam>
46-
/// <param name="stepFactory"></param>
53+
/// <param name="invoke">The delegate to invoke for the step.</param>
54+
/// <param name="lifetime">The service lifetime for the step. Defaults to <see cref="ServiceLifetime.Transient"/>.</param>
4755
/// <returns></returns>
48-
public PipelineBuilder<T> WithStep<TStep>(Func<TStep> stepFactory) where TStep : IPipelineStep<T>
56+
public PipelineBuilder<TContext> WithStep(
57+
Func<TContext, PipelineDelegate<TContext>, CancellationToken, Task> invoke,
58+
ServiceLifetime lifetime = ServiceLifetime.Transient)
4959
{
50-
_steps.Add(new(() => stepFactory()));
60+
var stepFactory = new Func<IServiceProvider, DelegatePipelineStep<TContext>>(_ => new DelegatePipelineStep<TContext>(invoke));
61+
62+
_services.Add(ServiceDescriptor.Describe(typeof(IPipelineStep<TContext>), stepFactory, lifetime));
63+
_services.Add(ServiceDescriptor.Describe(typeof(Lazy<IPipelineStep<TContext>>),
64+
sp => new Lazy<IPipelineStep<TContext>>(() => stepFactory(sp)), lifetime));
65+
5166
return this;
5267
}
5368
}

0 commit comments

Comments
 (0)