@ -72,40 +72,45 @@ Publishing by name with `new { OrderId = ..., CustomerEmail = ... }` triggers th
Dynamic subscription lets you register event handlers at runtime, using a string event name.
The recommended approach is to use `IocEventHandlerFactory`, which is the same mechanism ABP uses internally for typed handlers. It creates a new DI scope for each event, resolves a fresh handler instance, calls `HandleEventAsync`, then disposes the scope — so the handler can use normal constructor injection without any manual scope management:
```csharp
public override async Task OnApplicationInitializationAsync(
public override void ConfigureServices(ServiceConfigurationContext context)
@ -115,7 +120,7 @@ public class PartnerOrderHandler : IDistributedEventHandler<DynamicEventData>
- **`EventName`** — the string name that identifies the event
- **`Data`** — the raw event data payload (the deserialized `object` from the broker)
> `Subscribe` returns an `IDisposable`. Call `Dispose()` to unsubscribe the handler at runtime.
> `Subscribe` returns an `IDisposable`. Call `Dispose()` to unsubscribe the handler at runtime. For application-lifetime subscriptions, prefer module initialization (`OnApplicationInitializationAsync`) over subscribing inside an application service.
## Mixed Typed and Dynamic Handlers
@ -126,7 +131,8 @@ Typed and dynamic handlers coexist naturally. When both are registered for the s
// Dynamic handler — receives DynamicEventData for the same event
eventBus.Subscribe("OrderPlaced", new AuditLogHandler());
eventBus.Subscribe("OrderPlaced",
new IocEventHandlerFactory(scopeFactory, typeof(AuditLogHandler)));
```
When `OrderPlacedEto` is published (by type or by name), both handlers fire. The typed handler receives a fully deserialized `OrderPlacedEto` object. The dynamic handler receives a `DynamicEventData` wrapping the raw payload.
Use the `Subscribe` overload that accepts a string event name:
The recommended way to subscribe is to implement `IDistributedEventHandler<DynamicEventData>` and use `IocEventHandlerFactory`. This mirrors how ABP manages typed handlers — it creates a new DI scope per event, resolves a fresh handler instance, calls `HandleEventAsync`, then disposes the scope:
````csharp
public override void ConfigureServices(ServiceConfigurationContext context)
Where `myDistributedEventHandler` implements `IDistributedEventHandler<DynamicEventData>`.
> Do not inject `IServiceProvider` directly into a `SingleInstanceHandlerFactory`-based handler. Since the same instance is reused for every event, resolving scoped services directly from the root container causes a captive dependency and may throw a scope validation exception in development. Use `IocEventHandlerFactory` instead.