![]() |
VOOZH | about |
dotnet add package FluentChaining --version 1.0.4
NuGet\Install-Package FluentChaining -Version 1.0.4
<PackageReference Include="FluentChaining" Version="1.0.4" />
<PackageVersion Include="FluentChaining" Version="1.0.4" />Directory.Packages.props
<PackageReference Include="FluentChaining" />Project file
paket add FluentChaining --version 1.0.4
#r "nuget: FluentChaining, 1.0.4"
#:package FluentChaining@1.0.4
#addin nuget:?package=FluentChaining&version=1.0.4Install as a Cake Addin
#tool nuget:?package=FluentChaining&version=1.0.4Install as a Cake Tool
A lightweight library for implementing responsibility chains in fluent style.
Chain of responsibility is on OOP pattern outlined by GoF.
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
–– GoF
You can learn more about that pattern on refactoring.guru website.
IChain (IAsyncChain)You can create an IChain by using FluentChaining.CreateChain<TRequest, TResponse> method
or FluentChaining.CreateChain<TRequest> for chains that returns no value (Unit).
If your chain links have some dependencies to resolve, you can pass down an instance
of IEnumerable<ServiceDescriptor>, or simply an IServiceCollection that contains these dependencies.
Overloads for chains with async links are available as well.
public static IChain<Name, bool> CreateChain(IServiceCollection initialServices)
{
return FluentChaining.CreateChain<Name, bool>
(
initialServices,
builder => builder
.Then<LengthChecker>()
.Then<DigitCountChecker>()
.Then<SpecialSymbolsChecker>()
.FinishWith(() => true)
);
}
IChain (IAsyncChain) in the IServiceCollectionYou can also register you chains in DI container using extension methods.
Call AddFluentChaining method on IServiceCollection to start registration
and configure chain creation processes (optionally).
Scoped by default). Configuring lifetime for
individual chains is not supported, yet nothing stops you from calling AddFluentChaining multiple times.true, multiple chains with same (TRequest, TResponse) pair will be allowed, otherwise only the first
one will be used.The AddFluentChaining method will return IChainConfigurator instance, which has methods
for adding all types of chains.
public static void AddChainsToServiceCollection(IServiceCollection collection)
{
collection.AddFluentChaining(o =>
{
o.ChainLifetime = ServiceLifetime.Singleton;
o.AllowDuplicates = false;
})
.AddChain<Name, bool>
(
start => start
.Then<LengthChecker>()
.Then<DigitCountChecker>()
.Then<SpecialSymbolsChecker>()
.FinishWith(() => true)
)
.AddAsyncChain<Age, bool>
(
start => start
.Then<AgeChecker>()
.FinishFromResult(() => true)
);
}
To create a chain link, you simply need to implement an ILink interface or IAsyncLinkinterface (for async chains).
Links added in the chain support DI (as long as corresponding IServiceProvider can satisfy their dependencies).
To process a request by the chain you will need to call a Process method on the IChain or ProcessAsync
on IAsyncChain instance.
ILink implementation examplepublic class LengthChecker : ILink<Name, bool>
{
private readonly ValidationConfiguration _configuration;
public LengthChecker(ValidationConfiguration configuration)
{
_configuration = configuration;
}
public bool Process(Name request, SynchronousContext context, LinkDelegate<Name, SynchronousContext, bool> next)
{
if (request.Value.Length < _configuration.NameLength)
return false;
return next.Invoke(request, context);
}
}
IAsyncLink implementation examplepublic class AgeChecker : IAsyncLink<Age, bool>
{
private readonly ValidationConfiguration _configuration;
public AgeChecker(ValidationConfiguration configuration)
{
_configuration = configuration;
}
public Task<bool> Process(Age request, AsynchronousContext context, LinkDelegate<Age, AsynchronousContext, Task<bool>> next)
{
if (request.Value < _configuration.Age || context.CancellationToken.IsCancellationRequested)
return Task.FromResult(false);
return next.Invoke(request, context);
}
}
public static bool Validate(User user, IServiceProvider provider)
{
var nameValidator = provider.GetRequiredService<IChain<Name, bool>>();
var ageValidator = provider.GetRequiredService<IAsyncChain<Age, bool>>();
return nameValidator.Process(user.Name) && ageValidator.ProcessAsync(user.Age).Result;
}
Configuring links manually is definitely is a more reliable and stable approach. On the other hand it is more verbose, so for the sake of automation, or in case the link order is not important, you can use assembly scanning.
To add links from selected assemblies call ThenFromAssemblies method on your ILinkBuilder<,,> instance.
It receives AssemblyProviders as params, it will implicitly convert instances of Type and Assembly objects,
courtesy of FluentScanning.
If you want to have an ease of automation that assembly scanning offers, and still have some control over the order of
links in chain,
you can use LinkPriorityAttribute. Links will be sorted in descending order by their priority (the higher the
priority,
the earlier the link will be added), with priority 0 for ones without LinkPriorityAttribute.
.AddChain<Name, bool>
(
start => start
.ThenFromAssemblies(typeof(Scenario))
.FinishWith(() => true)
)
[LinkPriority(int.MaxValue)]
public class LengthChecker : ILink<Name, bool>
{
...
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on FluentChaining:
| Package | Downloads |
|---|---|
|
Itmo.Dev.Platform.Kafka
Package Description |
|
|
SourceKit.Generators.Builder
Type builder source generator |
|
|
Itmo.Dev.Platform.BackgroundTasks
Package Description |
|
|
Itmo.Dev.Platform.YandexCloud
Package Description |
|
|
Itmo.Dev.Platform.MessagePersistence
Package Description |
This package is not used by any popular GitHub repositories.
Updated FluentScanning package