0

我正在(反)序列化网络多人游戏的一些数据结构,并且对于每个要(反)序列化的数据结构,我只想定义一次(反)序列化的顺序以实现可维护性。

我可以使用 C# 的抽象类方法来实现我的目标,但是这样做有几个问题:

  1. 性能:我不想招致与使用“ref”参数对内置类型有关的装箱

  2. 性能:为每个(反)序列化操作添加额外的抽象方法调用也不理想

  3. 额外输入:我必须不必要地初始化我正在反序列化的所有变量,因为 C# 不允许我互换传递“ref”和“out”参数

如何避免重复数据结构(反)序列化的定义,同时避免上述部分或全部问题?

(我玩弄了代表和反射,但这个解决方案最容易找到我):

public struct ControllerSnapshot
{
    public Vector2 m_lStick;

    static private void Op(ref float lStickX, ref float lStickY, Op<float> op)
    {
        //define (de)serialization order here once and only once
        lStickX = op.Invoke(lStickX);
        lStickY = op.Invoke(lStickY);
    }
    public ControllerSnapshot(uLink.BitStream bitStream)
    {   
        OpRead<float> opRead = new OpRead<float>(bitStream);
        float lStickX,lStickY;
        lStickX = lStickY = 0.0f;//3.can't use "out"; have to match Op's "ref" params
        Op(ref lStickX,ref lStickY,opRead);

        m_lStick = new Vector2(lStickX,lStickY);
    }
    public void Serialize(uLink.BitStream bitStream)
    {
        OpWrite<float> opWrite = new OpWrite<float>(bitStream);
        Op(ref m_lStick.x, ref m_lStick.y, opWrite);
    }
};

//in order to make the above work this needs to be defined:
abstract class Op<T>
{
    public Op(uLink.BitStream bitStream)
    {
        m_bitStream = bitStream;
    }
    abstract public T Invoke(T arg);

    protected uLink.BitStream m_bitStream;
}
class OpRead<T>:Op<T>
{
    public OpRead(uLink.BitStream bitStream) : base(bitStream) { }
    override public T Invoke(T arg)
    {
        return m_bitStream.Read<T>();
    }
}
class OpWrite<T>:Op<T>
{
    public OpWrite(uLink.BitStream bitStream) : base(bitStream) { }
    override public T Invoke(T arg)
    {
        m_bitStream.Write<T>(arg);
        return arg;
    }
}   

//by contrast, the "obvious" code duplicates the order of (de)serialization, which I
//want to avoid, especially as (de)serialization becomes increasingly complex:
public ControllerSnapshot(uLink.BitStream bitStream)
{
    float lStickX,lStickY;
    lStickX = bitStream.Read<float>();
    lStickY = bitStream.Read<float>();

    m_lStick = new Vector2(lStickX,lStickY);
}
public void Serialize(uLink.BitStream bitStream)
{
    bitStream.Write<float>(m_lStick.x);
    bitStream.Write<float>(m_lStick.y);
}
4

1 回答 1

1

首先,我认为虚拟方法调用在这里不会产生任何影响——您正在序列化您的对象以通过网络传输。额外的几纳秒是没有意义的。

您提出的解决方案也让您重复自己 - 您仍然必须在序列化和反序列化中指定您的属性。

避免这种情况的唯一方法是通过某种方式指定应该序列化哪些字段并使用某种反射——就像 .NET 的序列化程序十年来一直在做的那样。

更新:

实际上,为什么不使用 Google 的Protobufs呢?

于 2013-04-24T05:30:38.543 回答