You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中动态构造事件处理器处理DDD领域事件的依赖注入问题

Fixing Dependency Injection for Domain Event Handlers with Autofac

Absolutely, you can get Autofac to inject dependencies into your domain event handlers—this is exactly the fix you need for that MissingMethodException. The root issue here is that Activator.CreateInstance can only instantiate classes with a parameterless constructor, but your handler needs an IOrderHistoryRepository dependency that Autofac should be managing. Let's rework your domain event infrastructure to leverage Autofac's container for resolving handlers, which will automatically inject any required services.

Step 1: Refactor Your Domain Event Dispatcher to Use Autofac

Instead of relying on Activator.CreateInstance, your dispatcher should pull handlers directly from Autofac's lifetime scope. This ensures dependencies are injected properly. Here's how to adjust your DomainEventsDispatcher:

public class DomainEventsDispatcher
{
    private readonly ILifetimeScope _lifetimeScope;

    // Inject Autofac's lifetime scope via constructor
    public DomainEventsDispatcher(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
    }

    public async Task DispatchEventsAsync(IEnumerable<IDomainEvent> domainEvents)
    {
        foreach (var domainEvent in domainEvents)
        {
            // Resolve all handlers for the current event type
            var handlerType = typeof(IHandler<>).MakeGenericType(domainEvent.GetType());
            var handlers = _lifetimeScope.ResolveAll(handlerType);

            // Invoke each handler (using dynamic to avoid messy reflection)
            foreach (dynamic handler in handlers)
            {
                await handler.HandleAsync((dynamic)domainEvent);
            }
        }
    }
}

Step 2: Register All Event Handlers with Autofac

Tell Autofac to automatically register every class that implements your IHandler<T> interface. This saves you from manually registering each handler one by one. Add this to your Autofac container setup:

var builder = new ContainerBuilder();

// Register all domain event handlers from your assembly (replace with your marker type)
builder.RegisterAssemblyTypes(typeof(OrderHistoryCreatedHandler).Assembly)
       .AsClosedTypesOf(typeof(IHandler<>))
       .InstancePerLifetimeScope();

// Register your dispatcher as a scoped service
builder.RegisterType<DomainEventsDispatcher>()
       .InstancePerLifetimeScope();

// Don't forget to register your repository dependency
builder.RegisterType<OrderHistoryRepository>()
       .As<IOrderHistoryRepository>()
       .InstancePerLifetimeScope();

// Build the container and integrate with ASP.NET Core
var container = builder.Build();
// ... rest of your ASP.NET Core setup to use Autofac as the DI provider

Step 3: Inject the Dispatcher into Your DbContext

Update your custom DbContext to accept the DomainEventsDispatcher via constructor injection, instead of using a static DomainEvents class. This keeps your code decoupled and aligned with DI best practices:

public class AppDbContext : DbContext
{
    private readonly DomainEventsDispatcher _eventsDispatcher;

    public AppDbContext(
        DbContextOptions<AppDbContext> options,
        DomainEventsDispatcher eventsDispatcher) : base(options)
    {
        _eventsDispatcher = eventsDispatcher;
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        // Collect all domain events from tracked entities first
        var domainEvents = ChangeTracker.Entries<YourBaseEntityType>()
            .Where(entry => entry.Entity.DomainEvents.Any())
            .SelectMany(entry => entry.Entity.DomainEvents)
            .ToList();

        // Save changes to the database first
        var saveResult = await base.SaveChangesAsync(cancellationToken);

        // Dispatch events AFTER saving (ensures events are based on persisted state)
        await _eventsDispatcher.DispatchEventsAsync(domainEvents);

        // Clear events from entities to avoid re-dispatching later
        foreach (var entry in ChangeTracker.Entries<YourBaseEntityType>())
        {
            entry.Entity.ClearDomainEvents();
        }

        return saveResult;
    }
}

Key Notes to Avoid Pitfalls

  • Skip Static Domain Events Classes: Static classes holding container references can lead to memory leaks or incorrect service lifetimes. Using an injected dispatcher is far safer.
  • Lifetime Alignment: InstancePerLifetimeScope ensures your handlers and their dependencies (like repositories) are scoped to the current request—ideal for ASP.NET Core web apps.
  • Support Multiple Handlers: ResolveAll lets you attach multiple handlers to a single domain event, a common and powerful DDD practice.

This setup will eliminate your MissingMethodException because Autofac handles instantiating your handlers with all required constructor dependencies—no parameterless constructor needed.

内容的提问来源于stack exchange,提问作者mirind4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:16:29