C#中动态初始化泛型对象的实现方案求助
解决方案
问题根源分析
- 构造函数参数不匹配:
entry.Value是List<IDomainEvent>类型,但DomainEventsBag<TDomainEvent>的构造函数需要IEnumerable<TDomainEvent>(比如IEnumerable<ADomainEvent>),直接传入会因类型不兼容报错。 - 反射实例类型问题:
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
相关产品推荐
相关产品推荐

