.NET 6中EventStore事件元数据(EventMetadata)的写入与反序列化问题
解决EventStore事件元数据写入与反序列化问题
看起来你遇到的核心问题是写入事件时没有携带必要的类型元数据,导致反序列化时无法确定要转换的目标类型。我们一步步来解决这个问题:
1. 定义元数据模型
首先创建一个元数据类,用来存储事件的类型标识(完整类型名,包含命名空间),这样反序列化时就能知道要转换成哪种类型:
public class EventMetadata { // 存储事件类型的完整名称(命名空间+类名) public string EventTypeFullName { get; set; } }
2. 修改事件写入代码,添加元数据
在生成EventData时,不再传入null作为元数据,而是序列化EventMetadata对象为字节数组后传入:
var myEvents = events.Select(@event => { var eventType = @event.GetType(); // 构建元数据,存入事件类型的完整名称 var metadata = new EventMetadata { EventTypeFullName = eventType.FullName }; // 序列化元数据为UTF-8字节数组 var metadataBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(metadata)); return new EventData( Guid.NewGuid(), eventType.Name, true, Serialize(@event), metadataBytes); // 传入元数据字节数组 }).ToArray(); return connection.AppendToStreamAsync(streamName, version, myEvents);
这里假设你的Serialize方法是将事件序列化为JSON字节数组,比如:
private byte[] Serialize(object @event) { var json = JsonConvert.SerializeObject(@event); return Encoding.UTF8.GetBytes(json); }
3. 修复反序列化扩展方法
你的原反序列化代码有个关键错误:Type.GetType(meta.GetType().ToString())是取EventMetadata的类型,而不是你要还原的事件类型。我们修改成从元数据中读取事件类型全名,再加载对应的类型:
using Newtonsoft.Json; using System.Text; using EventStore.ClientAPI; public static class EventDeserializer { public static object Deserialize(this ResolvedEvent resolvedEvent) { // 先检查元数据是否存在,避免空引用异常 if (resolvedEvent.Event.Metadata == null || resolvedEvent.Event.Metadata.Length == 0) { throw new InvalidOperationException("当前事件未携带元数据,无法执行反序列化"); } // 反序列化元数据 var metaJson = Encoding.UTF8.GetString(resolvedEvent.Event.Metadata); var meta = JsonConvert.DeserializeObject<EventMetadata>(metaJson); // 根据元数据中的类型全名加载目标类型 var eventType = Type.GetType(meta.EventTypeFullName); if (eventType == null) { throw new TypeLoadException($"无法加载类型: {meta.EventTypeFullName},请确认该类型所在程序集已被引用"); } // 反序列化事件数据 var dataJson = Encoding.UTF8.GetString(resolvedEvent.Event.Data); return JsonConvert.DeserializeObject(dataJson, eventType); } }
注意事项
- 如果你的事件类型位于单独的类库中,
Type.GetType可能需要指定程序集名称,比如meta.EventTypeFullName需要写成"YourNamespace.YourEvent, YourAssemblyName",这样才能正确加载跨程序集的类型。 - 确保写入和读取时使用的JSON序列化配置一致(比如日期格式、忽略空值等),避免反序列化失败。
- 可以在元数据中添加更多信息,比如事件创建时间、生产者标识等,方便后续的事件溯源和调试。
内容的提问来源于stack exchange,提问作者user1765862
相关产品推荐
相关产品推荐

