C# 正在尝试使用protobuf net序列化System.Numerics.Quaternion 背景信息

C# 正在尝试使用protobuf net序列化System.Numerics.Quaternion 背景信息,c#,.net-core,protobuf-net,.net-standard,C#,.net Core,Protobuf Net,.net Standard,我有一个.Net标准2.0类库,它使用Protobuf Net.grpc的代码优先方法来定义grpc服务。在这个定义中,我有一些类定义了不同的数据结构,我们使用这些数据结构来记录传感器数据,并使用protobuf net将其序列化。我的程序正在接收数十万个大型对象/秒(很快将扩展到数百万个),并打算在嵌入式环境中使用 问题 在我下面的课程中,我想加入System.Numerics.Quaterion作为成员。我似乎无法把这个连载出来。使用静态构造函数,RuntimeTypeModel抛出异常,因

我有一个.Net标准2.0类库,它使用Protobuf Net.grpc的代码优先方法来定义grpc服务。在这个定义中,我有一些类定义了不同的数据结构,我们使用这些数据结构来记录传感器数据,并使用protobuf net将其序列化。我的程序正在接收数十万个大型对象/秒(很快将扩展到数百万个),并打算在嵌入式环境中使用

问题 在我下面的课程中,我想加入System.Numerics.Quaterion作为成员。我似乎无法把这个连载出来。使用静态构造函数,RuntimeTypeModel抛出异常,因为在执行静态构造函数时,四元数模型已经以某种方式创建。因为这是一个类库,我非常希望避免使用gRPC服务在每个不同的程序中调用RuntimeTypeModel。我希望能找到一种方法来序列化这个系统

我尝试将这个静态构造函数运行时定义放在类层次结构的最高级别,但没有成功。仍然抛出异常

[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
    }
问题:
我想做的是可能的,还是应该创建自己的四元数类并定义隐式运算符?(我宁愿避免这种情况,因为处理数十亿个对象需要足够长的时间)

这最终是一个时间问题-当序列化程序试图反映
传感器数据
以准备序列化程序时,
IMUData
中的静态构造函数尚未执行,因此它用不完整的信息准备序列化程序,之后,静态构造函数尝试重新配置模型,但为时已晚

如果您使用C#9.0,您可以通过使用模块初始值设定项而不是静态构造函数来解决此问题(如果我们假设
SensorData
IMUData
在同一个模块中,这可能是一个安全的假设)。例如,以下操作很好:

[协议]
公共类IMUData:SensorData/,issensordata
{
[模块初始化器]
内部静态void Init()
{
RuntimeTypeModel.Default.Add(四元数类型),false)
.添加(“W”)
.添加(“X”)
.加上(“Y”)
.添加(“Z”);
}
请注意,如果您没有使用.NET 5(预览,当前),您可以自己定义必要的属性:

namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
内部密封类ModuleInitializeAttribute:属性{}
}


如果这不是一个选项,您可以简单地将模型配置代码放在应用程序中更早的位置—理想情况下是在启动期间,这样它就会在序列化程序尝试开始构建模型之前很久发生。

顺便说一句:依我看,这里的正确顺序是
X
Y
Z
W
,定义如下
四元数(float x,float y,float z,float w)
构造函数-如果是我,我会将它们排序为x=1,y=2,z=3,w=4;我这样说是因为这种类型实际上非常接近于一种内置的“类似元组的类型”,库会自动识别并使用它-如果是一个类型(没有合适的注释)如果有一个与所有成员匹配的构造函数(参数名上的大小写除外),则会推断它的意思是“构造函数参数顺序定义字段号”谢谢你,马克!很抱歉我没有看到模块初始值设定项。谢谢你花时间回答一个与protobuf net没有直接关系的问题!@craig他们在c#9中是新的,还没有发布iirc,但是如果你有.net 5 sdk,你可以使用它