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

C#中动态初始化泛型对象的实现方案求助

解决方案

问题根源分析

  1. 构造函数参数不匹配:entry.Value是List<IDomainEvent>类型,但DomainEventsBag<TDomainEvent>的构造函数需要IEnumerable<TDomainEvent>(比如IEnumerable<ADomainEvent>),直接传入会因类型不兼容报错。
  2. 反射实例类型问题:Activator.CreateInstance返回object,而MediatR的Publish<T>需要具体泛型类型参数才能匹配对应处理器,直接传入object无法触发正确逻辑。

具体实现代码

以下是修改后的Commit方法,同步/异步版本均提供:

同步版本

public void Commit()
{
    // 缓存反射方法,避免重复开销
    var castMethod = typeof(Enumerable).GetMethod(nameof(Enumerable.Cast)) 
        ?? throw new InvalidOperationException("无法获取Enumerable.Cast方法");
    
    var publishMethod = typeof(IMediator).GetMethods()
        .First(m => m.Name == nameof(IMediator.Publish) && m.GetParameters().Length == 1)
        ?? throw new InvalidOperationException("无法获取IMediator.Publish同步方法");

    foreach (var entry in domainEvents)
    {
        var eventType = entry.Key;
        
        // 1. 将List<IDomainEvent>转换为具体事件类型的IEnumerable
        var typedCastMethod = castMethod.MakeGenericMethod(eventType);
        var typedEvents = typedCastMethod.Invoke(null, new object[] { entry.Value });
        
        // 2. 创建对应的DomainEventsBag实例
        var eventBagType = typeof(DomainEventsBag<>).MakeGenericType(eventType);
        var domainEventsBag = Activator.CreateInstance(eventBagType, typedEvents);
        
        // 3. 反射调用MediatR的Publish方法,触发对应处理器
        var typedPublishMethod = publishMethod.MakeGenericMethod(eventBagType);
        typedPublishMethod.Invoke(mediator, new object[] { domainEventsBag });
    }

    // 清空已发布的事件
    domainEvents.Clear();
}

异步版本(推荐,适配MediatR主流场景)

如果使用异步模式,可将IDomainEventsAggregator改为异步接口,并实现如下:

public async Task CommitAsync(CancellationToken cancellationToken = default)
{
    var castMethod = typeof(Enumerable).GetMethod(nameof(Enumerable.Cast)) 
        ?? throw new InvalidOperationException("无法获取Enumerable.Cast方法");
    
    var publishMethod = typeof(IMediator).GetMethods()
        .First(m => m.Name == nameof(IMediator.Publish) && m.GetParameters().Length == 2)
        ?? throw new InvalidOperationException("无法获取IMediator.Publish异步方法");

    foreach (var entry in domainEvents)
    {
        var eventType = entry.Key;
        
        var typedCastMethod = castMethod.MakeGenericMethod(eventType);
        var typedEvents = typedCastMethod.Invoke(null, new object[] { entry.Value });
        
        var eventBagType = typeof(DomainEventsBag<>).MakeGenericType(eventType);
        var domainEventsBag = Activator.CreateInstance(eventBagType, typedEvents);
        
        var typedPublishMethod = publishMethod.MakeGenericMethod(eventBagType);
        await (Task)typedPublishMethod.Invoke(mediator, new object[] { domainEventsBag, cancellationToken });
    }

    domainEvents.Clear();
}

额外优化建议

  • 强类型存储优化:可修改事件存储结构为Dictionary<Type, object>,其中object实际是List<TDomainEvent>,添加事件时直接存入强类型列表,后续无需类型转换:
    private Dictionary<Type, object> domainEvents = new();
    
    public void AddEvent<TDomainEvent>(TDomainEvent @event) where TDomainEvent : IDomainEvent
    {
        var eventType = typeof(TDomainEvent);
        if (!domainEvents.TryGetValue(eventType, out var list))
        {
            list = new List<TDomainEvent>();
            domainEvents[eventType] = list;
        }
        ((List<TDomainEvent>)list).Add(@event);
    }
    
  • 异常处理增强:在反射调用环节添加try-catch,处理类型转换或调用失败的边界情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:00:03