C# clrmq上的序列化和反序列化

C# clrmq上的序列化和反序列化,c#,serialization,zeromq,C#,Serialization,Zeromq,我目前正在使用ZeroMQ的clrmq绑定在C#中设计一个网络包装器 我的问题是,我正试图想出一种反序列化和序列化的方法 透明的;也就是说,网络包装器可以以字节形式传输任何对象,而不知道或关心其类型,并且可以反序列化到另一端的正确类型 我有如下类别的继承人 public interface ITransmission { Type Type { get; } } public abstract class Transmission<T> : ITransmission {

我目前正在使用ZeroMQ的clrmq绑定在C#中设计一个网络包装器

我的问题是,我正试图想出一种反序列化和序列化的方法 透明的;也就是说,网络包装器可以以字节形式传输任何对象,而不知道或关心其类型,并且可以反序列化到另一端的正确类型

我有如下类别的继承人

public interface ITransmission
{
    Type Type { get; }
}

public abstract class Transmission<T> : ITransmission
{
    public Type Type { get { return typeof(T); } }
}
公共接口ITTransmission
{
类型{get;}
}
公共抽象类传输:ITTransmission
{
公共类型类型{get{return typeof(T);}
}
其思想是序列化已实现传输类型的对象;传输 它们在clrmq上以字节形式存储,并在另一端反序列化

我的理想解决方案是

  • 能够将任何类型的对象序列化为字节数组格式,而无需属性修饰或非常小的属性修饰(因此,上述想法使用传输对象)
  • 能够将接收到的字节数组格式反序列化为类型化对象
  • 人们目前正在使用或做什么来解决透明序列化和反序列化的问题?在某个时候,速度将是一个因素,但在这个时候,我只是想找出有哪些选择

    这里隐含的限制是网络库需要引用包含要传输的类型的所有程序集吗

    此外,另一个问题是,这是一种可行的方法,还是服务器和客户机从一开始就应该是强类型的


    感谢您的阅读。

    我在一个在线多人游戏中成功地做到了这一点,使用的反射可能会根据您的需求满足您的需求

    这里有一个链接描述了我是如何做到这一点的:

    简而言之,我是如何序列化/反序列化数据的:我创建了一个名为“GameMessage”的类,它使用反射来序列化/反序列化自己。然后,每个消息类型都将简单地从该类继承,并神奇地拥有一个ToByte()函数和接受byte[]的构造函数:

    public class GameMessage 
        {
    
            private static int SortFieldInfo(FieldInfo left, FieldInfo right)
            {
                if (left.Equals(right))
                {
                    return 0;
                }
    
                if (right.Name == "ID")
                    return 1;
                else if (right.FieldType.Name == "String")
                    return -1;
                else 
                    return 0;
            }
            public GameMessage(){}
            public GameMessage(byte[] data)
            {
                List<byte> bytes = new List<byte>();
                List<FieldInfo> info = new List<FieldInfo>(this.GetType().GetFields());
    
                info.Sort(SortFieldInfo);
                int idx = 0;
    
                for (int i = 0; i < info.Count; i++)
                {
                    if (info[i].FieldType.Name == "String")// is string)
                    {
                        string value;
                        UInt16 size;
    
                        if (i != info.Count - 1)
                        {
                            size = BitConverter.ToUInt16(data, idx);
                            idx += 2;
    
                            value = ASCIIEncoding.ASCII.GetString(data, idx, size);
                            idx += size;
                        }
                        else
                        {
                            value = ASCIIEncoding.ASCII.GetString(data, idx, data.Length - idx);
                            idx += data.Length - idx;
                        }
    
                        info[i].SetValue(this,value);
                    }
                    else
                    {
                        if (info[i].Name != "ID")
                        {
                            Type[] types = new Type[2] { data.GetType(), idx.GetType() };
                            object[] values = new object[2] { data, idx };
    
                            info[i].SetValue(this, typeof(BitConverter).GetMethod("To" + info[i].FieldType.Name, types).Invoke(null, values));
                            idx += Marshal.SizeOf(info[i].FieldType);
                        }
                        else
                        {
                            idx += sizeof(ID);
                        }
                    }
                }
    
            }
            public byte[] ToByte()
            {
                List<byte> bytes = new List<byte>();
                List<FieldInfo> info = new List<FieldInfo>(this.GetType().GetFields());
                info.Sort(SortFieldInfo);
    
                for(int i=0;i<info.Count;i++)
                {
                    if (info[i].FieldType.Name == "String")
                    {
                        if (i != info.Count - 1)
                        {
                            bytes.AddRange(BitConverter.GetBytes(((UInt16)((string)info[i].GetValue(this)).Length)));
                        }
    
                        bytes.AddRange(ASCIIEncoding.ASCII.GetBytes((string)info[i].GetValue(this)));
                    }
                    else
                    {
                        bytes.AddRange((byte[])typeof(BitConverter).GetMethod("GetBytes", new Type[] { info[i].FieldType }).Invoke(null, new object[] { info[i].GetValue(this) }));
                    }
              }
    
                return bytes.ToArray();
            }
        }
    
    公共类游戏消息
    {
    私有静态int-SortFieldInfo(FieldInfo左,FieldInfo右)
    {
    如果(左。等于(右))
    {
    返回0;
    }
    如果(right.Name==“ID”)
    返回1;
    else if(right.FieldType.Name==“String”)
    返回-1;
    其他的
    返回0;
    }
    公共游戏消息(){}
    公共游戏消息(字节[]数据)
    {
    列表字节=新列表();
    列表信息=新列表(this.GetType().GetFields());
    信息排序(SortFieldInfo);
    int-idx=0;
    对于(int i=0;i对于(int i=0;i用户dferraro的解决方案是一个很好的解决方案。但我认为现在人们可以用C#中的序列化做得更好。我强烈建议您将ZeroMQ与Google的Protobuf框架作为序列化和消息传递组件的传输配对


    请看一下的.NET实现。我不会详细介绍它的实现方面,因为它的文档非常丰富,关于它的StackOverflow这里已经有很多很好的问题。事实上,Protobuf的C#implementation的作者经常无所事事,并且会用标签回答任何问题。

    速度是一个关键因素吗?我在过去对反射做过类似的事情。那是几年前的事了,但简而言之,我做的是有一些代码,可以使用反射迭代对象中的每个成员,然后将其打包到一个字节数组中。接收端也做了同样的事情。它非常灵活,而且我非常灵活您好,速度在某个时候会是一个因素,但现在我只是收集一些想法。您的解决方案有多快/慢?我可以使用界面中的类型信息使其更快吗?它足够快,满足我的需要,这是相当高的性能要求(实际上是一个2D在线多人游戏)那是6或7年前我提出的;)。我想它已经过时了。我从来没有听说过protobuf这个东西,但它看起来很棒。谢谢你给出了非常详尽的答案,而且