这是我的 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
这样的方法,所以我不知道我能做什么。
通过使用 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
(或任何其他默认值)并继续反序列化。这样,您可以避免在处理数据的同时破坏反序列化过程的异常。