尝试使用 protobuf-net 序列化 System.Numerics.Quaternion [英] Trying to serialize System.Numerics.Quaternion using protobuf-net

查看:23
本文介绍了尝试使用 protobuf-net 序列化 System.Numerics.Quaternion的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a .Net Standard 2.0 class library that uses Protobuf-net.grpc's code first approach to define a gRPC service. In this definition I have classes defining different data structures that we are using to record sensor data and serialize this out using protobuf-net. My programs are ingesting serveral hundred thousand large objects /s (which will soon scale into the millions) and are intended to be used in embedded environments.

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

In my class below, I would like to include as a member a System.Numerics.Quaterion. I cannot seem to get this serialized out. Using static constructors, the RuntimeTypeModel throws exceptions as the Quaternion model has somehow already been created by the time the static constructor is executed. As this is a class library, and I desperately want to avoid invoking the RuntimeTypeModel in each different program using the gRPC service. I'm hoping to find a way to serialize the System.Numerics.Quaternion.

我曾尝试将此静态构造函数运行时定义置于类层次结构的最高级别,但无济于事.仍然抛出异常.

I have tried placing this static constructor runtime definition at the highest level of the class hierarchy to no avail. Exceptions still thrown.

[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
    }

问题

我想要做的甚至是可能的,还是我应该简单地创建自己的四元数类并定义隐式运算符?(我宁愿避免这种情况,因为处理数十亿这样的对象需要足够长的时间)

Question

Is what I would like to do even possible, or should I simply create my own Quaternion class and define implicit operators? (I'd rather avoid this as processing billions of these objects takes long enough)

推荐答案

这归根结底是一个时序问题——当序列化器试图反思 SensorData 以准备序列化器时, 中的静态构造函数>IMUData 还没有执行,所以它用不完整的信息准备序列化器,然后稍后静态构造函数尝试重新配置模型 - 太晚了.

This is ultimately a timing problem - when the serializer attempts to reflect on SensorData to prepare the serializer, the static constructor in IMUData has not yet executed, so it prepares the serializer with incomplete information, and then later the static constructor tries to reconfigure the model - too late.

如果你使用 C# 9.0,你可以通过使用模块初始化器而不是静态构造函数来解决这个问题(如果我们假设 SensorDataIMUData 在同一个模块中,这可能是一个安全的假设).以下工作正常,例如:

If you use C# 9.0, you can fix this by using a module initializer instead of a static constructor (if we assume that SensorData and IMUData are in the same module, which is probably a safe assumption). The following works fine, for example:

[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(目前为预览版),您可以自己定义必要的属性:

Note that if you're not using .NET 5 (preview, currently), you can define the necessary attribute yourself:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    internal sealed class ModuleInitializerAttribute : Attribute { }
}


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


If this isn't an option, you can simply put the model configuration code much earlier in your application - ideally during startup, so that it happens long before the serializer attempts to start building models.

这篇关于尝试使用 protobuf-net 序列化 System.Numerics.Quaternion的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆