• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Migrating from MediatR to LiteBus

Sascha Оффлайн

Sascha

Заместитель Администратора
Команда форума
Администратор
Регистрация
9 Май 2015
Сообщения
1,605
Баллы
155


This guide provides a step-by-step technical walkthrough for migrating a .NET application from MediatR to LiteBus. It maps MediatR's concepts directly to their LiteBus equivalents, focusing on code and configuration changes.

Since MediatR is shifting to a commercial model, LiteBus offers a powerful, free, and open-source alternative with a more ambitious feature set.

Core Philosophy: From Generic to Semantic


The primary difference between the two libraries is their approach to abstractions:

  • MediatR uses a generic IRequest<TResponse> for both commands and queries.
  • LiteBus provides distinct ICommand<TResult>, IQuery<TResult>, and IEvent interfaces.

This semantic distinction in LiteBus enforces Command Query Separation (CQS) at the compiler level, making your application's intent clearer.

Step 1: Update Project Dependencies


First, replace the MediatR packages with the LiteBus equivalents.

Remove MediatR:


dotnet remove MediatR




Add LiteBus:


# Core DI extension (pulls in Command, Query, Event modules)
dotnet add package LiteBus.Extensions.Microsoft.DependencyInjection

# Optional: For referencing only abstractions in domain/app layers
dotnet add package LiteBus.Commands.Abstractions
dotnet add package LiteBus.Queries.Abstractions
dotnet add package LiteBus.Events.Abstractions



Step 2: Update Dependency Injection (Program.cs)


The registration process is similar. LiteBus scans assemblies to discover handlers automatically.

Before (MediatR):


builder.Services.AddMediatR(cfg =>
{
cfg.LicenseKey = "<License Key here>";
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
});




After (LiteBus):


builder.Services.AddLiteBus(liteBus =>
{
var appAssembly = typeof(Program).Assembly;

// Each module scans for its specific constructs (handlers, validators, etc.)
liteBus.AddCommandModule(module => module.RegisterFromAssembly(appAssembly));
liteBus.AddQueryModule(module => module.RegisterFromAssembly(appAssembly));
liteBus.AddEventModule(module => module.RegisterFromAssembly(appAssembly));
});



Step 3: Convert Message Contracts


This is a direct mapping of interfaces.

Requests (Commands and Queries)

  • IRequest -> ICommand
  • IRequest<TResponse> -> ICommand<TResponse> (for state changes) or IQuery<TResponse> (for data retrieval).

Before (MediatR):


// Command
public class ShipOrderCommand : IRequest { ... }

// Query
public class GetProductQuery : IRequest<ProductDto> { ... }




After (LiteBus):


// Command
public class ShipOrderCommand : ICommand { ... }

// Query
public class GetProductQuery : IQuery<ProductDto> { ... }



Notifications (Events)

  • INotification -> IEvent or a Plain Old C# Object (POCO).

Before (MediatR):


public class OrderShippedEvent : INotification { ... }




After (LiteBus):


// Option 1: Using the interface
public class OrderShippedEvent : IEvent { ... }

// Option 2: Using a POCO (recommended for domain events)
public class OrderShippedEvent { ... }



Step 4: Convert Handlers


Handler interfaces also map directly.

Before (MediatR):


public class ShipOrderCommandHandler : IRequestHandler<ShipOrderCommand> { ... }
public class GetProductQueryHandler : IRequestHandler<GetProductQuery, ProductDto> { ... }
public class OrderShippedEventHandler : INotificationHandler<OrderShippedEvent> { ... }




After (LiteBus):


public class ShipOrderCommandHandler : ICommandHandler<ShipOrderCommand> { ... }
public class GetProductQueryHandler : IQueryHandler<GetProductQuery, ProductDto> { ... }
public class OrderShippedEventHandler : IEventHandler<OrderShippedEvent> { ... }



Step 5: Convert Pipeline Behaviors and Processors


MediatR uses IPipelineBehavior for cross-cutting concerns and has separate pre/post-processors. LiteBus unifies this into a structured pipeline of Pre-Handler, Post-Handler, and Error-Handler.

  • IRequestPreProcessor<TRequest> -> ICommandPreHandler<TCommand>
  • IRequestPostProcessor<TRequest, TResponse> -> ICommandPostHandler<TCommand, TResponse>
  • IPipelineBehavior logic can be split into pre and post handlers.

Let's convert a MediatR LoggingBehavior.

Before (MediatR):


public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken ct)
{
// Pre-logic
_logger.LogInformation("Handling {RequestName}", typeof(TRequest).Name);
var response = await next();
// Post-logic
_logger.LogInformation("Handled {RequestName}", typeof(TRequest).Name);
return response;
}
}




After (LiteBus):

The logic is split into two distinct, globally-scoped handlers.


// This runs BEFORE every command.
public class GlobalLoggingPreHandler : ICommandPreHandler
{
public Task PreHandleAsync(ICommand command, CancellationToken cancellationToken)
{
_logger.LogInformation("Handling {CommandName}", command.GetType().Name);
return Task.CompletedTask;
}
}

// This runs AFTER every command.
public class GlobalLoggingPostHandler : ICommandPostHandler
{
public Task PostHandleAsync(ICommand command, object? result, CancellationToken cancellationToken)
{
_logger.LogInformation("Handled {CommandName}", command.GetType().Name);
return Task.CompletedTask;
}
}



Step 6: Convert Exception Handling


MediatR uses IRequestExceptionHandler and IRequestExceptionAction. LiteBus uses a single, powerful IErrorHandler concept that can be scoped globally or to a specific message.

Before (MediatR):


public class MyExceptionHandler : IRequestExceptionHandler<MyRequest, MyResponse, MyException>
{
public Task Handle(MyRequest request, MyException exception, RequestExceptionHandlerState<MyResponse> state, CancellationToken cancellationToken)
{
// Handle the exception, potentially setting a response
state.SetHandled(new MyResponse());
return Task.CompletedTask;
}
}




After (LiteBus):


public class MyErrorHandler : ICommandErrorHandler<MyCommand>
{
public Task HandleErrorAsync(MyCommand command, object? messageResult, Exception exception, CancellationToken cancellationToken)
{
if (exception is MyException myException)
{
// Access the execution context to set a result and stop the exception
AmbientExecutionContext.Current.Abort(new MyCommandResult());
}
// If Abort() is not called, the original exception will be re-thrown
return Task.CompletedTask;
}
}



Step 7: Update Dispatching Code


Instead of a single IMediator, LiteBus provides specific interfaces.

Before (MediatR):


public class MyController
{
private readonly IMediator _mediator;
public async Task MyAction()
{
await _mediator.Send(new MyCommand());
await _mediator.Publish(new MyEvent());
}
}




After (LiteBus):


public class MyController
{
private readonly ICommandMediator _commandMediator;
private readonly IEventPublisher _eventPublisher;
public async Task MyAction()
{
await _commandMediator.SendAsync(new MyCommand());
await _eventPublisher.PublishAsync(new MyEvent());
}
}



More Features of LiteBus


MediatR is, by its own definition, a "low-ambition" library. LiteBus is more ambitious and provides built-in solutions for complex, enterprise-level problems. Once migrated, you have access to:

  • Durable Command Inbox: Guarantee at-least-once execution of critical commands with the [StoreInInbox] attribute. This provides message-queue-like resilience for in-process operations without adding heavy infrastructure.
  • Advanced Event Concurrency: Configure event handlers to run sequentially or in parallel, both within priority groups and across them. This is essential for performance tuning complex event-driven workflows.
  • First-Class Streaming: Use IStreamQuery<T> and IAsyncEnumerable<T> to efficiently handle large datasets without high memory usage.
  • DI-Agnostic Core: Decoupled from any specific DI container, with official support for Microsoft DI and Autofac.
  • Advanced Handler Filtering: Use tags and dynamic predicates to select which handlers run in a given context, enabling patterns like feature flags or environment-specific logic.

This guide covers the direct mapping of concepts for a smooth migration from MediatR. However, the true benefits of LiteBus are found in the features that go beyond basic mediation. To explore these capabilities in detail, the

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

provides in-depth guides on the Durable Command Inbox, advanced event concurrency, handler filtering, and other best practices.



Источник:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу