Interlink 1.5.1
Prefix Reserveddotnet add package Interlink --version 1.5.1
NuGet\Install-Package Interlink -Version 1.5.1
<PackageReference Include="Interlink" Version="1.5.1" />
<PackageVersion Include="Interlink" Version="1.5.1" />
<PackageReference Include="Interlink" />
paket add Interlink --version 1.5.1
#r "nuget: Interlink, 1.5.1"
#:package Interlink@1.5.1
#addin nuget:?package=Interlink&version=1.5.1
#tool nuget:?package=Interlink&version=1.5.1
Interlink
Interlink is a lightweight and modern mediator library for .NET, designed to decouple your code through request/response and notification patterns. Built with simplicity and performance in mind, it helps streamline communication between components while maintaining a clean architecture.
โจ Features
- ๐งฉ Simple mediator pattern for request/response
- ๐ Publish/Subscribe notification system
- ๐ง Pipeline behaviors (logging, validation, etc.)
- ๐ง Clean separation of concerns via handlers
- ๐ช Dependency injection support out of the box
- ๐ Pre and Post Processors for enhanced lifecycle control
- ๐ Assembly scanning for automatic handler registration
- ๐งช Custom service factory injection
- ๐ Pipeline ordering via attributes or configuration
- ๐จ Dedicated
HandlerNotFoundException - โ Compatible with .NET Standard 2.0+ to .NET 10
- ๐ฆ Optional packages: Logging, FluentValidation, ASP.NET Core, Analyzer
๐ฆ Installation
dotnet add package Interlink
Optional packages:
dotnet add package Interlink.Extensions.Logging
dotnet add package Interlink.Extensions.Validation
dotnet add package Interlink.AspNetCore
dotnet add package Interlink.Analyzers
โ๏ธ Setup
Register Interlink in Program.cs (or Startup.cs):
builder.Services.AddInterlink();
Scan a specific assembly:
builder.Services.AddInterlink(typeof(MyHandler).Assembly);
Configure pipeline behaviors and optional custom factory:
builder.Services.AddInterlink(options =>
{
// Open-generic behaviors (order is optional; lower runs first / outermost)
options.AddBehavior(typeof(LoggingBehavior<,>), order: 0);
options.AddBehavior(typeof(ValidationBehavior<,>), order: 1);
// Optional custom resolution factory
options.ServiceFactory = type => /* your custom resolver */;
}, typeof(MyHandler).Assembly);
With the extension packages:
builder.Services.AddInterlink(typeof(MyHandler).Assembly);
builder.Services.AddInterlinkLogging();
builder.Services.AddInterlinkValidation(typeof(MyValidator).Assembly);
builder.Services.AddInterlinkAspNetCore(); // registers exception filter
๐จ Request / Response Pattern
1. Define a request and handler
using Interlink;
using Interlink.Contracts;
public class GetAllPets
{
public sealed record Query : IRequest<List<string>>;
public sealed class Handler : IRequestHandler<Query, List<string>>
{
public Task<List<string>> Handle(Query request, CancellationToken cancellationToken)
{
var pets = new List<string> { "Dog", "Cat", "Fish" };
return Task.FromResult(pets);
}
}
}
2. Send the request
[ApiController]
[Route("api/[controller]")]
public class PetController(ISender sender) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAllPets(CancellationToken cancellationToken)
{
var pets = await sender.Send(new GetAllPets.Query(), cancellationToken);
return Ok(pets);
}
}
If no handler is registered, Send throws HandlerNotFoundException.
๐ฃ Notifications (Publish / Subscribe)
1. Define a notification
public sealed class UserCreated(string userName) : INotification
{
public string UserName { get; } = userName;
}
2. Create one or more handlers
public sealed class SendWelcomeEmail : INotificationHandler<UserCreated>
{
public Task Handle(UserCreated notification, CancellationToken cancellationToken)
{
Console.WriteLine($"Welcome email sent to {notification.UserName}");
return Task.CompletedTask;
}
}
public sealed class WriteAuditLog : INotificationHandler<UserCreated>
{
public Task Handle(UserCreated notification, CancellationToken cancellationToken)
{
Console.WriteLine($"Audit: user {notification.UserName} created");
return Task.CompletedTask;
}
}
3. Publish
public class AccountService(IPublisher publisher)
{
public async Task RegisterUser(string username)
{
// Save to DB...
await publisher.Publish(new UserCreated(username));
}
}
๐งฌ Pipeline Behaviors
Pipeline behaviors wrap the handler and can run logic before and after it.
Signature (correct order)
public interface IPipelineBehavior<in TRequest, TResponse>
where TRequest : notnull
{
Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken);
}
Example behavior
public sealed class TimingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
var sw = Stopwatch.StartNew();
var response = await next(cancellationToken);
sw.Stop();
Console.WriteLine($"{typeof(TRequest).Name} took {sw.ElapsedMilliseconds} ms");
return response;
}
}
Ordering
Use the attribute (lower value runs first / outermost):
[PipelineOrder(1)]
public sealed class FirstBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
Console.WriteLine("First behavior");
return await next(cancellationToken);
}
}
[PipelineOrder(2)]
public sealed class SecondBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
Console.WriteLine("Second behavior");
return await next(cancellationToken);
}
}
Or supply the order when registering:
builder.Services.AddInterlink(options =>
{
options.AddBehavior(typeof(FirstBehavior<,>), order: 1);
options.AddBehavior(typeof(SecondBehavior<,>), order: 2);
});
๐ Pre and Post Processors
Pre-processors run before the pipeline.
Post-processors run after a successful pipeline.
public sealed class MyRequestPreProcessor : IRequestPreProcessor<GetAllPets.Query>
{
public Task Process(GetAllPets.Query request, CancellationToken cancellationToken)
{
Console.WriteLine("[Pre] GetAllPets");
return Task.CompletedTask;
}
}
public sealed class MyRequestPostProcessor : IRequestPostProcessor<GetAllPets.Query, List<string>>
{
public Task Process(GetAllPets.Query request, List<string> response, CancellationToken cancellationToken)
{
Console.WriteLine($"[Post] returned {response.Count} pets");
return Task.CompletedTask;
}
}
They are discovered automatically by AddInterlink().
๐ Built-in Logging Behavior
dotnet add package Interlink.Extensions.Logging
builder.Services.AddInterlinkLogging();
This registers LoggingBehavior<TRequest, TResponse>, which logs:
- request start
- successful completion + elapsed milliseconds
- exceptions
โ FluentValidation Integration
dotnet add package Interlink.Extensions.Validation
// Registers ValidationBehavior + scans for IValidator<T>
builder.Services.AddInterlinkValidation(typeof(CreateUserValidator).Assembly);
Example validator:
public sealed class CreateUserValidator : AbstractValidator<CreateUser.Command>
{
public CreateUserValidator()
{
RuleFor(x => x.Email).NotEmpty().EmailAddress();
RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
}
}
When validation fails, a FluentValidation.ValidationException is thrown (mapped to 400 by the ASP.NET Core filter if you use it).
๐ ASP.NET Core Integration
dotnet add package Interlink.AspNetCore
builder.Services.AddControllers();
builder.Services.AddInterlinkAspNetCore(); // adds InterlinkExceptionFilter
The filter maps:
| Exception | HTTP Status | Response |
|---|---|---|
HandlerNotFoundException |
404 | ProblemDetails |
ValidationException* |
400 | ValidationProblemDetails |
* FluentValidation support is optional and detected at runtime (no hard dependency).
๐ Analyzer (missing handler detection)
dotnet add package Interlink.Analyzers
Produces diagnostic ILINK001 (warning) when a type implements IRequest<TResponse> but no corresponding IRequestHandler<TRequest, TResponse> is found in the compilation.
๐ฆ API Overview
Core contracts
public interface IRequest<out TResponse> { }
public interface IRequestHandler<in TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken);
}
public interface INotification { }
public interface INotificationHandler<in TNotification>
where TNotification : INotification
{
Task Handle(TNotification notification, CancellationToken cancellationToken);
}
Sender & Publisher
public interface ISender
{
Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default);
}
public interface IPublisher
{
Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default)
where TNotification : INotification;
}
Pipeline
public delegate Task<TResponse> RequestHandlerDelegate<TResponse>(CancellationToken cancellationToken = default);
public interface IPipelineBehavior<in TRequest, TResponse>
where TRequest : notnull
{
Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken);
}
Pre / Post processors
public interface IRequestPreProcessor<in TRequest> where TRequest : notnull
{
Task Process(TRequest request, CancellationToken cancellationToken);
}
public interface IRequestPostProcessor<in TRequest, in TResponse> where TRequest : notnull
{
Task Process(TRequest request, TResponse response, CancellationToken cancellationToken);
}
Exception
public class HandlerNotFoundException : InvalidOperationException
{
public Type RequestType { get; }
public Type? HandlerType { get; }
}
๐ Roadmap status
| Version | Status | Highlights |
|---|---|---|
| 1.0 โ 1.3 | โ Released | Core mediator, notifications, pipelines, pre/post, performance |
| 1.4 | โ Released | .NET Standard 2.0+ |
| 1.5 | โ Current | Logging, Validation, ASP.NET Core, Analyzer, exceptions, ordering fixes |
Future ideas
- Request cancellation / timeout behaviors
- Metrics & tracing support
- Dynamic / externalized pipeline configuration
๐ License
MIT License ยฉ ManuHub
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
-
net10.0
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Interlink:
| Package | Downloads |
|---|---|
|
Interlink.AspNetCore
ASP.NET Core integration for the Interlink mediator library (filters, exception handling, helpers). |
|
|
Interlink.Extensions.Logging
Built-in logging pipeline behavior for the Interlink mediator library. |
|
|
Interlink.Extensions.Validation
FluentValidation integration for the Interlink mediator library. |
GitHub repositories
This package is not used by any popular GitHub repositories.