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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:49:09