选择基于序列化数据的反序列化程序



很抱歉标题不好,但我不确定如何命名它。我需要找到一种方法来处理以下问题:

我有一堂课

public class Event
{
public ushort Id;
}

我的框架的这个类使用者必须继承他们的自定义事件。因此,假设他们是否要创建以下内容:

public class OnConnect : Event
{
...
}

该 ID用于在服务器/客户端环境中标识序列化的 byte[] 数据传输时,必须将字节数据反序列化到哪个事件。所以基本上在 byte[] 数据中,前 2 个字节包含 ushort id。然后我可以阅读此内容,获取关联类型并调用正确的反序列化程序。

但正如时间所示,一个潜在的问题或错误的用法是,消费者忘记在他们的自定义事件中分配一个唯一的 ushort id,或者对多个事件使用相同的 id,因为他们没有检查这一点。教他们使用枚举作为示例,往往会引起一些额外的问题。无论如何,即使看起来很容易管理,我们的报告也声称这是一个常见问题。

所以我现在想自动化它以消除这个可能的问题。但是我真的很难找到解决这个问题的可能方法,因为我有以下结构:

  • 服务器/客户端环境,我选择的过程必须在两端提供相同的结果
  • 事件
  • 本身不能用于初始化此数字,因为首次使用事件 x 时的顺序并不总是相同的。

首先,我想到了使用类似IRequireId左右的接口进行依赖注入,在我的检索 medthod 上,我x.componentes.Where(c=>c is IRequireId)为事件分配一个唯一的 id 并将其存储在其他地方,当事件初始化时,我可以从那里获取 id。这样做的问题是,我无法确保 x.components.Where 以与网络上其他对等体相同的顺序检索组件。因此,可以分配不同的 id。

所以我认为 DI 不在路上。其他人是否有任何想法,或者关于如何确保我的检索方法确实保存任何顺序的想法,以便在网络上的每个对等体上都相同?

在撰写本文时,我想也许使用HashSet并编写我自己的GetHashcode,该确实在每个对等体上重现相同的哈希代码。然后遍历哈希集并在IRequireId接口上执行 DI。但是,我怎样才能编写一个在网络上的每个对等体上都相同的哈希代码生成呢?那需要再次和id。该死。

请帮忙 x)我目前有点迷茫。 蒂亚协同

编辑

我忘了注意,因为有人已经问过这个问题,为什么不简单地将类型作为字符串添加到字节数组中呢?

由于这是一个网络环境,我们确实关心字节数组的大小。如果我们只想发送一个事件中的 4 个字节的数据,并且 byte[] 本身是 20 个字节长,因为包含该类型的字符串有 16 个字节,那么这是不可接受的。

编辑

感谢带有类名的提示,我现在能够解决它。

  • 我使用类名生成哈希码
  • 然后,我可以使用它来确保我的 get 方法中的顺序
  • 最后,我可以通过创建一个 ushort id 来做 DI

真棒感谢帮助

我以不同的方式解决了类似的情况。我将总结细节。选择适合您的最佳选项。

  • 您可以将预定义的 Id 值分配给序列化程序,并根据需要重写 -

    public interface IEvent
    {
    ushort Id { get; }
    }
    public class Event: IEvent
    {
    public virtual ushort Id { get { return 500; } } // a generic code for generic Event
    }
    public class OnConnect: Event
    {
    public override ushort Id { get { return 505; } } // a more customised error code for generic Event
    }
    

    此方案的好处是可以获得预定义的代码,并且没有人需要分配它们,因为它们是只读属性。

  • 第二种方法是使用类名作为代码。由于所有类都将具有唯一的名称,因此只要正确维护名称,您将始终获得每个事件的唯一键。比以前的方法不那么严格,但仍然可以维护 -

    public interface IEvent
    {
    ushort Id { get; }
    }
    public class Event: IEvent
    {
    public virtual ushort Id {
    get {
    var name = this.GetType().Name.Replace("Event", "");
    return name == "" ? "Generic" : name;
    //will return "Generic" for base
    }
    }
    }
    public class OnConnectEvent: Event
    {
    //no need to override the base class will handle everything, just make sure
    //the name is correct
    //will return "OnConnect"
    }
    public class OnDisconnectEvent: Event
    {
    //no need to override the base class will handle everything, just make sure
    //the names are correct
    //will return "OnDisconnect"
    }
    

    您可以通过将事件类设为abstract来进一步自定义,以防您不需要通用默认事件。

如果我理解,您正在将对象序列化为字节数组,并且您需要某种标识符来告诉您原始类型是什么,以便您可以将其反序列化为正确的类型。

为什么不只使用序列化对象的Type而不是数字?或者,如果这本身需要序列化,则类型的名称?这样就无需将数字与类型匹配。您已经拥有该类型。

最新更新