C# 从不同对象构造字节数组的舒适方式

C# comfortable way to construct byte array from different objects

我正在寻找一种快速简单地实施此范例的方法:

MyByteArray mb = new MyByteArray();
mb.Add<byte>(bytevalue);
mb.Add<float>(floatvalue);
mb.Add<string>(str);
mb.Add<MyClass>(object);

然后从 mb 中获取 byte[],通过 RPC 调用将其作为字节数据包发送(使用相同的技术在另一端解码)。

我找到了 MemoryStream,但对于这个简单的操作来说它看起来开销太大了。

你能帮帮我吗?谢谢。

你要找的是BinaryWritter。但出于纯粹的逻辑原因,它仍然需要一个 Stream 来写入。唯一符合您需要的 Stream 是 MemoryStream。

你害怕性能开销吗?您可以从现有字节数组创建 MemoryStream;

    byte [] buffer = new byte[1024];
    using (var memoryStream = new MemoryStream(buffer))
    {
        using (var binaryWriter = new BinaryWriter(memoryStream))
        {
            binaryWriter.Write(1.2F); // float
            binaryWriter.Write(1.9D); // double
            binaryWriter.Write(1); // integer
            binaryWriter.Write("str"); // string
        }
    }
    // buffer is filled with your data now. 

这看起来像是 Protocol Buffers 的情况,您可以查看 protobuf-net

首先,让我们装饰类。

[ProtoContract]
class User
{
  [ProtoMember(1)]
  public int Id { get; set; }

  [ProtoMember(2)]
  public string Name { get; set; }
}

[ProtoContract]
class Message
{
  [ProtoMember(1)]
  public byte Type { get; set; }

  [ProtoMember(2)]
  public float Value { get; set; }

  [ProtoMember(3)]
  public User Sender { get; set; }
}

然后我们创建消息。

var msg = new Message
{
  Type = 1,
  Value = 1.1f,
  Sender = new User
  {
    Id = 8,
    Name = "user"
  }
};

现在,我们可以使用 ProtoBuf 的序列化器来完成我们所有的工作。

// memory
using (var mem = new MemoryStream())
{
  Serializer.Serialize<Message>(mem, msg);
  var bytes = mem.GetBuffer();
}

// file
using (var file = File.Create("message.bin")) Serializer.Serialize<Message>(file, msg);

实现此目的的一个棘手方法是在 .net

中结合使用内置 class
 class Program
    {
        static void Main(string[] args)
        {    
            Program  program   =  new Program(); 
            var listBytes  = new List<byte>();
               listBytes.Add( program.CastToBytes("test")); 
               listBytes.Add(program.CastToBytes(5));         
        }

备注 对于自定义对象,您必须定义 implicit operator 属性或所有对象的转换方式

        public byte[] CastToBytes<T>(T value)            
        {
            //this will cover most  of primitive types 

            if (typeof(T).IsValueType)
            {
                return BitConverter.GetBytes((dynamic)value);
            }

            if (typeof(T) == typeof(string))
            {
                return Encoding.UTF8.GetBytes((dynamic) value); 
            }
            //for a custom  object  you  have to  define  the rules 
            else
            {
                var formatter = new BinaryFormatter();
                var memoryStream = new MemoryStream();
                formatter.Serialize(memoryStream, value);
                return  memoryStream.GetBuffer();     
            }                                    
        }

    }