@@ -280,20 +280,11 @@ The same analyzers and code fixes are provided for the opposite anti-pattern,
280280known as [sync over async ](https :// devblogs.microsoft.com/pfxteam/should-i-expose-synchronous-wrappers-for-asynchronous-methods/),
281281where a synchronous command is executed asynchronously .
282282
283- <!-- #core -->
284-
285- ## Message Bus
286-
287- The default implementation lives in a separate package [Merq .Core ](https :// www.nuget.org/packages/Merq.Core)
288- so that application components can take a dependency on just the interfaces .
289-
290- [](https://www.nuget.org/packages/Merq.Core)
291- [](https://www.nuget.org/packages/Merq.Core)
283+ ## Hosting
292284
293- <!-- #implementation -->
294285The default implementation of the message bus interface `IMessageBus ` has
295286no external dependencies and can be instantiated via the `MessageBus ` constructor
296- directly .
287+ directly by an application host .
297288
298289The bus locates command handlers and event producers via the passed -in
299290`IServiceProvider ` instance in the constructor :
@@ -308,14 +299,9 @@ bus.Execute(new MyCommand());
308299 bus.Observe<MyEvent>().Subscribe (e => Console.WriteLine(e.Message));
309300```
310301
302+ Merq integrates out of the box with [dependency injection for .NET ](https:// learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection), making it straightforward to
303+ properly register the bus and all command handlers and event producers.
311304
312- <!-- #implementation -->
313-
314- When using [dependency injection for .NET ](https:// learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection),
315- the [Merq .DependencyInjection ](https ://www .nuget .org /packages /Merq .DependencyInjection ) package
316- provides a simple mechanism for registering the message bus:
317-
318- <!-- #di -->
319305```csharp
320306var builder = WebApplication .CreateBuilder (args );
321307...
@@ -324,7 +310,9 @@ builder.Services.AddMessageBus();
324310
325311All command handlers and event producers need to be registered with the
326312services collection as usual , using the main interface for the component ,
327- such as `ICommandHandler <T >` and `IObservable <TEvent >`.
313+ such as `ICommandHandler <T >` and `IObservable <TEvent >`. In addition , if
314+ you use the `IMessageBus .CanExecute <T >` method , handlers need to also be
315+ registered with the `ICanExecute <T >` interface .
328316
329317> NOTE : *Merq * makes no assumptions about the lifetime of the registered
330318> components , so it 's up to the consumer to register them with the desired
@@ -346,7 +334,10 @@ This allows to simply mark all command handlers and event producers as
346334builder .Services .AddServices ();
347335```
348336
349- ### Telemetry and Monitoring
337+ This package emits all registrations at compile-time using source generators ,
338+ so run -time performance is not affected at all .
339+
340+ ## Telemetry and Monitoring
350341
351342The core implementation of the `IMessageBus ` is instrumented with `ActivitySource ` and
352343`Metric `, providing out of the box support for [Open Telemetry ](https :// learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs)-based monitoring, as well
@@ -384,35 +375,7 @@ Example rendering from the included sample console app:
384375
385376! [dotnet - counters screenshot ](https :// raw.githubusercontent.com/devlooped/Merq/main/assets/img/dotnet-counters.png)
386377
387- ## Duck Typing Support
388-
389- < ! -- #duck -- >
390- Being able to loosely couple both events (and their consumers ) and command execution (from their
391- command handler implementations ) is a key feature of Merq . To take this decoupling to the extreme ,
392- Merq allows a similar capability as allowed by the TypeScript / JavaScript in VSCode : you can just
393- copy / paste an event / command definition as * source * into your assembly , and perform the regular
394- operations with it (like `Observe ` an event and `Execute ` a command ), in a " duck typing" manner .
395-
396- As long as the types ' full name match, the conversion will happen automatically. Since this
397- functionality isn 't required in many scenarios, and since there are a myriad ways to implement
398- such an object mapping functionality , the `Merq .Core ` package only provides the hooks to enable
399- this , but does not provide any built - in implementation for it . In other words , no duck typing
400- is performed by default .
401-
402- The [Merq .AutoMapper ](https :// www.nuget.org/packages/Merq.AutoMapper) package provides one such
403- implementation , based on the excelent [AutoMapper ](https :// automapper.org/) library. It can be
404- registered with the DI container as follows :
405-
406- ```csharp
407- builder .Services .AddMessageBus <AutoMapperMessageBus >();
408- // register all services, including handlers and producers
409- builder .Services .AddServices ();
410- ```
411-
412- < ! -- #duck -- >
413-
414- < ! -- #perf -- >
415- # Performance
378+ ## Performance
416379
417380The performance of Merq is on par with the best implementations of the
418381the same pattern , for example [MediatR ](https :// www.nuget.org/packages/mediatr).
@@ -438,7 +401,42 @@ Intel Core i9-10900T CPU 1.90GHz, 1 CPU, 20 logical and 10 physical cores
438401
439402< ! -- ./ src / Merq .Benchmarks / BenchmarkDotNet .Artifacts / results / Merq .MerqVsMediatR .Benchmark - report - github .md -- >
440403
441- < ! -- #perf -- >
404+ ## Abstractions
405+
406+ [! [Version ](https :// img.shields.io/nuget/vpre/Merq.Abstractions.svg?color=royalblue)](https://www.nuget.org/packages/Merq.Abstractions)
407+ [! [Downloads ](https :// img.shields.io/nuget/dt/Merq.Abstractions.svg?color=green)](https://www.nuget.org/packages/Merq.Abstractions)
408+
409+ < ! -- #abstractions -- >
410+ The [Merq .Abstractions ](https :// www.nuget.org/packages/Merq.Abstractions)
411+ contains just the interfaces for [Merq ](https :// www.nuget.org/packages/Merq) for scenarios where
412+ messages are shared across multiple assemblies or defined separately from the main app host .
413+ < ! -- #abstractions -- >
414+
415+ ## Duck Typing
416+
417+ Being able to loosely couple both events (and their consumers ) and command execution (from their
418+ command handler implementations ) is a key feature of Merq . To take this decoupling to the extreme ,
419+ Merq allows a similar capability as allowed by the TypeScript / JavaScript in VSCode : you can just
420+ copy / paste an event / command definition as * source * into your assembly , and perform the regular
421+ operations with it (like `Observe ` an event and `Execute ` a command ), in a " duck typing" manner .
422+
423+ As long as the types ' full name match, the conversion will happen automatically. Since this
424+ functionality isn 't required in many scenarios, and since there are a myriad ways to implement
425+ such an object mapping functionality , the `Merq .Core ` package only provides the hooks to enable
426+ this , but does not provide any built - in implementation for it . In other words , no duck typing
427+ is performed by default .
428+
429+ The [Merq .AutoMapper ](https :// www.nuget.org/packages/Merq.AutoMapper) package provides one such
430+ implementation , based on the excelent [AutoMapper ](https :// automapper.org/) library. It can be
431+ registered with the DI container as follows :
432+
433+ ```csharp
434+ builder .Services .AddMessageBus <AutoMapperMessageBus >();
435+ // register all services, including handlers and producers
436+ builder .Services .AddServices ();
437+ ```
438+
439+ < ! -- #core -- >
442440
443441< ! -- #ci -- >
444442
0 commit comments