如何安全地反序列化MessagePack消息而不抛出异常?

问题描述 投票:0回答:1

这是我的 DTO:

public class InvocationMessage
{
    public string MethodName { get; set; }
    public object?[]? Args { get; set; }
}

最初我使用

MessagePackSerializer.Serialize(Msg, ContractlessStandardResolver.Options);

对其进行序列化

然后在反序列化时,我想将

object
Args
转换为具体类型。如果没有自定义格式化程序,这是不可能的。所以我写了一篇:

public InvocationMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
    var result = new InvocationMessage
    {
        MethodName = reader.ReadString()
    };

    // Hardcoded for testing purpose
    var argTypes = new Type[] { typeof(SomeType) };
    if (reader.TryReadArrayHeader(out int count))
    {
        result.Args = new object?[count];

        for (int i = 0; i < argTypes.Length; i++)
        {
            result.Args[i] = MessagePackSerializer.Deserialize(argTypes[i], ref reader,
                ContractlessStandardResolver.Options.WithSecurity(MessagePackSecurity.UntrustedData));
        }
    }

    return result;
}

public void Serialize(ref MessagePackWriter writer, InvocationMessage value, MessagePackSerializerOptions options)
{
    var methodName = Encoding.UTF8.GetBytes(value.MethodName);

    writer.WriteString(methodName);

    if (value.Args is not null && value.Args.Length > 0)
    {
        writer.WriteArrayHeader(value.Args.Length);

        foreach (var arg in value.Args)
        {
            MessagePackSerializer.Serialize(ref writer, arg, ContractlessStandardResolver.Options);
        }
    }
}

不幸的是,当我尝试反序列化时,总是会抛出异常。像这样的:

var msg = new InvocationMessage
{
    MethodName = "sometestname",
    Args = new object?[]
        {
            new 
            {
                Test = 3
            },
            new
            {
                ReceiverId = "12ds",
                Content = "s",
            },
            new 
            {
                Test2 = 5
            },
        }
};

这是因为我想将一些未知类型反序列化为我的

SomeType
,或者因为我的
SomeType
想要
string
作为属性
ReceiverId
并获得
int
。有很多情况会抛出异常。

但我需要避免抛出,因为这对我的应用程序来说是一个很大的性能问题。没有像

TryDeserialize
这样的方法,所以我不知道我能做什么。

c# serialization deserialization msgpack
1个回答
0
投票

通过使用 try-catch 块处理反序列化过程中潜在的异常,您可以安全地反序列化 MessagePack 消息,而不会引发异常。这是一个例子:

public InvocationMessage Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
    var result = new InvocationMessage
    {
        MethodName = reader.ReadString()
    };

    if (reader.TryReadArrayHeader(out int count))
    {
        result.Args = new object?[count];

        for (int i = 0; i < count; i++)
        {
            try
            {
                result.Args[i] = MessagePackSerializer.Deserialize<object>(ref reader, options);
            }
            catch (Exception ex)
            {
                result.Args[i] = null;
            }
        }
    }

    return result;
}

如果抛出异常,它将相应的

Args
元素设置为
null
(或任何其他默认值)并继续反序列化。这样,您可以避免在处理数据的同时破坏反序列化过程的异常。

© www.soinside.com 2019 - 2024. All rights reserved.