背景信息
我有一个.Net标准2.0类库,它使用Protobuf-net.grpc的代码优先方法来定义gRPC服务。在这个定义中,我有定义不同数据结构的类,我们使用这些数据结构记录传感器数据,并使用protobuf将其序列化。我的程序正在摄取服务器十万大对象/s (它很快将扩展到数百万),并打算用于嵌入式环境。
问题
在我下面的班级里,我想加入一个System.Numerics.Quaterion作为会员。我似乎不能把这个串行化。使用静态构造函数,RuntimeTypeModel抛出异常,因为在执行静态构造函数时,已经以某种方式创建了四元数模型。因为这是一个类库,我非常希望避免使用RuntimeTypeModel服务在每个不同的程序中调用gRPC。我希望找到一种序列化System.Numerics.Quaternion的方法。
我尝试将这个静态构造函数运行时定义放在类层次结构的最高级别上,但没有效果。异常仍被抛出。
[ProtoContract]
public class IMUData : SensorData, ISensorData
{
static IMUData()
{
RuntimeTypeModel.Default.Add(typeof(Quaternion), false)
.Add("W")
.Add("X")
.Add("Y")
.Add("Z");
}
... //Other members
[ProtoMember(8)]
public Quaternion Orientation
{
get; set;
}
... //Other methods and members
}问题
是我想要做的甚至可能,还是我应该简单地创建我自己的四元数类并定义隐式运算符?(我宁愿避免这种情况,因为处理这些对象的时间足够长)
发布于 2020-10-29 10:25:53
这最终是一个计时问题--当序列化程序试图对SensorData进行反思以准备序列化程序时,IMUData中的静态构造函数尚未执行,因此它使用不完整的信息准备序列化程序,然后静态构造函数尝试重新配置模型--太晚了。
如果您使用C# 9.0,您可以使用模块初始化器而不是静态构造函数来修复这个问题(如果我们假设SensorData和IMUData在同一个模块中,这可能是一个安全的假设)。例如,以下功能运行良好:
[ProtoContract]
public class IMUData : SensorData //, ISensorData
{
[ModuleInitializer]
internal static void Init()
{
RuntimeTypeModel.Default.Add(typeof(Quaternion), false)
.Add("W")
.Add("X")
.Add("Y")
.Add("Z");
}请注意,如果您不使用.NET 5(当前预览),您可以自己定义必要的属性:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
internal sealed class ModuleInitializerAttribute : Attribute { }
}如果这不是一个选项,您可以简单地将模型配置代码放在应用程序的早期--最好是在启动期间,这样在序列化程序试图开始构建模型之前很久就会出现这种情况。
https://stackoverflow.com/questions/64581076
复制相似问题