根据序列化数据选择反序列化器

时间:2017-07-05 17:16:54

标签: c#

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

我有一个班级

public class Event
{
     public ushort Id;
}

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

public class OnConnect : Event
{
     ...
}

ID 用于在服务器/客户端环境中识别,当串行化的byte []数据被传输时,您必须对字节数据进行反序列化。所以基本上在byte []数据中,前2个字节包含ushort id。然后我可以阅读这个,得到关联类型并调用正确的反序列化器。

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

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

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

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

所以我认为DI不在路上。是否有其他人有任何想法或想法如何确保我的检索方法确实保存了任何订单,以便它在网络上的每个同行中都是相同的?

在编写本文时,我想到了可能使用HashSet并编写自己的GetHashcode,它会在每个对等端上重现相同的哈希码。然后迭代哈希集并在IRequireId接口上执行DI。但是,如何在网络上的每个对等体上编写相同的哈希码生成?这将需要并再次id。该死的。

请帮助x)我目前有点失落。 tia Synergi

修改

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

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

修改

对于类名的提示,我现在能够解决它。

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

非常棒的帮助

2 个答案:

答案 0 :(得分:0)

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

为什么不使用序列化对象的Type而不是数字呢?或者,如果这个本身需要序列化,那么类型的名称?这样就不需要将数字与类型相匹配。你已经有了这种类型。

答案 1 :(得分:0)

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

  • 您可以将预定义的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来进一步定制。