Convert an array of different value types to a byte array

后端 未结 3 767
花落未央
花落未央 2020-12-21 22:41

This is what I\'ve come up with so far, but it doesn\'t seem very optimal, any ideas on better approaches?

public void ToBytes(object[] data, byte[] buffer)
         


        
3条回答
  •  不知归路
    2020-12-21 23:16

    Well, you could have a map like this:

    private static readonlyDictionary> Converters = 
        new Dictionary>()
    {
        { typeof(string), o => Encoding.UTF8.GetBytes((string) o) },
        { typeof(bool), o => BitConverter.GetBytes((bool) o) },
        { typeof(char), o => BitConverter.GetBytes((char) o) },
        ...
    };
    
    public static void ToBytes(object[] data, byte[] buffer)
    {
        int offset = 0;
    
        foreach (object obj in data)
        {
            if (obj == null)
            {
                // Or do whatever you want
                throw new ArgumentException("Unable to convert null values");
            }
            Func converter;
            if (!Converters.TryGetValue(obj.GetType(), out converter))
            {
                throw new ArgumentException("No converter for " + obj.GetType());
            }
    
            byte[] obytes = converter(obj);
            Buffer.BlockCopy(obytes, 0, buffer, offset, obytes.Length);
            offset += obytes.Length;
        }
    }
    

    You're still specifying the converter for each type, but it's a lot more compact than the if/else form.

    There are various other ways of constructing the dictionary, btw. You could do it like this:

    private static readonly Dictionary> Converters = 
            new Dictionary>();
    
    static WhateverYourTypeIsCalled()
    {
        AddConverter(Encoding.UTF8.GetBytes);
        AddConverter(BitConverter.GetBytes);
        AddConverter(BitConverter.GetBytes);
    }
    
    static void AddConverter(Func converter)
    {
        Converters.Add(typeof(T), x => converter((T) x));
    }
    

    I see another answer has suggested binary serialization. I'm personally not keen on "opaque" serialization schemes like that. I like to know exactly what's going to be in the data in a way that means I can port it to other platforms.

    I would point out, however, that your current scheme doesn't give any sort of delimiter - if you have two strings, you'd have no idea where one stopped and the other started, for example. You also don't store the type information - that may be okay, but it may not be. The variable length issue is usually more important. You might consider using a length-prefix scheme, like the one in BinaryWriter. Indeed, BinaryWriter may well be a simpler solution in general. You'd probably want to still have a map of delegates, but make them actions taking a BinaryWriter and a value. You could then build the map by reflection, or just a hardcoded list of calls.

    Then you'd just initialize a BinaryWriter wrapping a MemoryStream, write each value to it appropriately, then call ToArray on the MemoryStream to get the results.

提交回复
热议问题