Hi all, I have a lot of long boring work ahead of me, unless this long shot comes up roses.

I have a lot of classes I need to add a ToByteArray() method to, and I'm wondering if Visual studio 2015 has
any tricks up its sleeve where I can create some macro or template to generate the methods, instead of manually writing them for many scores of classes.

Here is an example of the method based on the properties of the class.

class Class
    {
        public int var1 { get; set; }
        public uint var2 { get; set; }
        public byte var3 { get; set; }

        public byte[] ToByteArray()
        {
            byte[][] baArray = {
                BitConverter.GetBytes(var1),
                BitConverter.GetBytes(var2),
                new byte[1] { var3 }
            };

            int isize = 0;
            foreach (byte[] bdata in baArray)
            {
                isize += bdata.Length;
            }

            byte[] bRtn = new byte[isize];
            int ioffset = 0;

            foreach (byte[] bdata in baArray)
            {
                Buffer.BlockCopy(bdata, 0, bRtn, ioffset, bdata.Length);
                ioffset += bdata.Length;
            }
            return bRtn;

        }

    }

Of course each class will have a varying number of properties with different names.

I really do know I'm clutching at straws, but I've been surprised before, and my search skills and unwordyness
let me down a lot in my reasearch.

As always, even just the correct things I ought to be searching for will be a great help.

Thanks for reading.

Edited 3 Months Ago by Suzie999

Forgot to mention, I got as far as Reflection and a way of printing out the type name and values of properties, but that's about it, I don't know if it helps me really.

Class c = new Class();
            //byte[] res = c.ToByteArray();
            //MessageBox.Show(res.Length.ToString());

            foreach (PropertyInfo prop in typeof(Class).GetProperties())
            {
                Debug.WriteLine("{0} {1} = {2}",
                    prop.PropertyType,
                    prop.Name, 
                    prop.GetValue(c, null)
                    );
            }

I suppose using that reflection trick, I could do something like the following, but it's still a whole lot of headache.

Debug.WriteLine("public byte[] ToByteArray()");
            Debug.WriteLine("{");
            Debug.WriteLine("byte[][] baArray = {");
            Debug.WriteLine("");
            foreach (PropertyInfo prop in typeof(Class).GetProperties())
            {
                Debug.WriteLine("BitConverter.GetBytes(" + prop.Name + ");");
            }
            Debug.WriteLine("};");
            Debug.WriteLine("int isize = 0;");
            Debug.WriteLine("foreach (byte[] bdata in baArray)");
            Debug.WriteLine("{");
            Debug.WriteLine("isize += bdata.Length;");
            Debug.WriteLine("}");
            Debug.WriteLine("byte[] bRtn = new byte[isize];");
            Debug.WriteLine("int ioffset = 0;");
            Debug.WriteLine("foreach (byte[] bdata in baArray)");
            Debug.WriteLine("{");
            Debug.WriteLine("Buffer.BlockCopy(bdata, 0, bRtn, ioffset, bdata.Length);");
            Debug.WriteLine("ioffset += bdata.Length;");
            Debug.WriteLine("}");
            Debug.WriteLine("return bRtn;");
            Debug.WriteLine("}");

Edited 3 Months Ago by Suzie999

I have no C# or Visual Studio advice to offer. I'm a Code-Blocks C/C++ guy, so if you need something specific to C# or Visual Studio, stop reading here... ;)

Disqualifiers aside, is this a continuation of your earlier threads sending class objects down a TCP stream socket? I'm unfamiliar with BitConverter, so I looked it up here.

https://msdn.microsoft.com/en-us/library/93ae9768(v=vs.110).aspx

What stood out to me is this line...

The order of bytes in the array returned by the GetBytes method depends on whether the computer architecture is little-endian or big-endian.

You are sending these integer values through the socket Big Endian, correct? I am seeing a lack of host-to-network function calls in your code. I am wondering if you want to use those functions instead of the BitConverter functions unless you can assume that the receiving machine has the same endianness. These bytes are being transmitted between different machines, right?

http://beej.us/guide/bgnet/output/html/multipage/htonsman.html

Thanks for your input.

Yes It is to do with my project, I'm still exploring my options, and been waylayed a bit on coding tangents, which I welcome as I'm in no hurry, like this ToByteArray, and exploring sslStream for secureness.

I had thought about endianness, but did not fret too much because of BitConverter.IsLittleEndian property, I need only to reverse the bytes to get conformity.

I've even been fantasizing about writing a proper serilization class for classes, a project for which I am ill qualified, but a girl can dream :)

I have a lot of classes I need to add a ToByteArray() method to

What's the purpose of this method? Typically I'd suggest utilizing the serialization classes already present in .NET:

public static class BinaryWrapper
{
    public static byte[] Serialize<T>(T obj)
    {
        using (var stream = new MemoryStream())
        {
            var formatter = new BinaryFormatter();

            formatter.Serialize(stream, obj);
            stream.Flush();
            stream.Position = 0;

            return stream.ToArray();
        }
    }

    public static T Deserialize<T>(byte[] b)
    {
        using (var stream = new MemoryStream(b))
        {
            var formatter = new BinaryFormatter();

            stream.Seek(0, SeekOrigin.Begin);

            return (T)formatter.Deserialize(stream);
        }
    }
}

However, it somewhat depends on your use case whether this meets your needs.

I looked at that, but from what I could tell, you have to jump through many hoops with regards padding issues with structures and such.

I'll take another look, maybe I got the wrong end of the stick.

Thanks.

You still haven't mentioned the use case, so I can only speculate. However, it sounds very much like a binary serialization isn't what you want because there are compatiblity and portability concerns.

You mean issues with different machine word size?

Here is a demo class to show what I'm thinking of.
Client calls ToByteArray on transaction class, and sends the resulting array over network. Server creates a new transaction class taking the array as argument to constructor.

class Transaction
    {
        public static int ID { get; set; }
        public double AmountDue { get; set; }
        public double AmountPaid { get; set; }
        public double ChangeGiven { get; set; }
        public string Product { get; set; }

        public Transaction()
        {
            ID++;
            Product = "Test message sent for testing the test";
        }

        // TODO on startup, this constructor must be called
        // first to initialize ID to last database entry
        public Transaction(int id)
        {
            ID = id++;

        }

        public Transaction(byte[] argByte)
        {
            FromByteArray(argByte);
        }

        public void Print()
        {
            MessageBox.Show(
                ID.ToString() + Environment.NewLine
                + AmountDue.ToString() + Environment.NewLine
                + AmountPaid.ToString() + Environment.NewLine
                + ChangeGiven.ToString() + Environment.NewLine
                + Product);
        }

        private void FromByteArray(byte[] argArray)
        {
            ID = BitConverter.ToInt32(argArray, 0);
            AmountDue = BitConverter.ToDouble(argArray, 4);
            AmountPaid = BitConverter.ToDouble(argArray, 12);
            ChangeGiven = BitConverter.ToDouble(argArray, 20);
            Product = BitConverter.ToString(argArray, 28);
        }

        public byte[] ToByteArray()
        {
            byte[][] baArray =
                {
                    BitConverter.GetBytes(ID),
                    BitConverter.GetBytes(AmountDue),
                    BitConverter.GetBytes(AmountPaid),
                    BitConverter.GetBytes(ChangeGiven),
                    Encoding.ASCII.GetBytes(Product)
                  };
            int isize = 0;
            foreach (byte[] bdata in baArray)
            {
                isize += bdata.Length;
            }
            byte[] bRtn = new byte[isize];
            int ioffset = 0;
            foreach (byte[] bdata in baArray)
            {
                Buffer.BlockCopy(bdata, 0, bRtn, ioffset, bdata.Length);
                ioffset += bdata.Length;
            }
            return bRtn;
        }

    }

You mean issues with different machine word size?

Byte order would be a larger concern. In your case, I'd favor serializing to JSON for your packet.

I've decided to just override ToString method with a deliminator, send those bytes, split the string and convert values at other end.

Thanks all.

The article starter has earned a lot of community kudos, and such articles offer a bounty for quality replies.