ServiceStack OnDeserialized 等价物

ServiceStack OnDeserialized Equivalent

我正在实时反序列化一个websocket消息。在我收到的消息(json 的字符串)中有一个 unix 时间戳(长)。一旦每个对象被反序列化,我需要它尽快调用一个方法,以便我可以捕获消息发送和接收之间的延迟。使用 Json.NET 很简单,我只是将此方法添加到我的 DataContract class:

[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
    Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(TimestampLong).LocalDateTime;
    Delay = DateTime.Now - Timestamp;
}

出于各种原因,我更愿意继续使用 ServiceStack 的反序列化器,但我似乎无法找到一种方法来做到这一点。我确实找到了将近 10 年前的 this Whosebug post,但我希望它有所改变,或者有一个我可以使用的解决方法。

ServiceStack.Text doesn't support these attributes by default, but you can implement serialization callbacks with Custom Type Configuration,例如:

JsConfig<MyType>.OnDeserializedFn = o =>
{
    o.OnDeserialized(null);
    return o;
};

SerializationHookTests.cs 展示了如何使用类型过滤器为使用此帮助器的类型连接这些回调:

static void AddSerializeHooksForType<T>()
{
    Type type = typeof(T);
    System.Reflection.MethodInfo[] typeMethods = type
      .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    var onSerializingMethods = typeMethods.Where(m => 
        m.GetCustomAttributes(typeof(OnSerializingAttribute), true).Length > 0);
    var OnDeserializedMethods = typeMethods.Where(m => 
        m.GetCustomAttributes(typeof(OnDeserializedAttribute), true).Length > 0);
    var OnSerializedMethods = typeMethods.Where(m => 
        m.GetCustomAttributes(typeof(OnSerializedAttribute), true).Length > 0);
    Object[] Parameters = { null };

    if (onSerializingMethods.Any()) {
        ServiceStack.Text.JsConfig<T>.OnSerializingFn = s => {
            foreach (var method in onSerializingMethods)
                method.Invoke(s, Parameters);
            return s;
        };
    }
    if (OnSerializedMethods.Any()) {
        ServiceStack.Text.JsConfig<T>.OnSerializedFn = s => {
            foreach (var method in OnSerializedMethods)
                method.Invoke(s, Parameters);
        };
    }
    if (OnDeserializedMethods.Any()) {
        ServiceStack.Text.JsConfig<T>.OnDeserializedFn = s => {
            foreach (var method in OnDeserializedMethods)
                method.Invoke(s, Parameters);
            return s;
        };
    }
}

您可以使用以下类型连接:

AddSerializeHooksForType<HookTest>();

调用所需回调的位置,例如:

public class HookTest
{
    /// <summary>
    /// Will be executed when deserializing starts
    /// </summary>
    [OnDeserializing]
    protected void OnDeserializing(StreamingContext ctx) { }

    /// <summary>
    /// Will be executed when deserializing finished
    /// </summary>
    [OnDeserialized]
    protected void OnDeserialized(StreamingContext ctx) { }

    /// <summary>
    /// Will be executed when serializing starts
    /// </summary>
    [OnSerializing]
    protected void OnSerializing(StreamingContext ctx) { }

    /// <summary>
    /// Will be executed when serializing finished
    /// </summary>
    [OnSerialized]
    protected void OnSerialized(StreamingContext ctx) { }
}