how can read The Bytes of an object variable (that its in RAM now) and recreate the object by it Bytes in C#?

StackOverflow https://stackoverflow.com/questions/13601666

  •  03-12-2021
  •  | 
  •  

Question

i want to access the bytes of an object in C# okey for example :

Serializing an class in WCF the serializer read the all bytes of class object and Finally SOAP message !

Some Thing Like This You Know A Way To Read object Bytes And Recreate object by its Bytes

//x_obj created and we allocate an address & size of RAM (memory) to it Now its byts structure is in the RAM

X_calss x_obj = new X_class(); 

//and now we want to read the x_obj bytes in RAM
unsafe byte[] READ(X_class x_obj){
 xobj_pointer = &x_obj;//pointer to address of obj in RAM
 byte[] xobj_bytes = read_from(xobj_pointer,sizeof(x_obj));//Some Way To Read Byte of x_obj
 return xobj_bytes;
}
// and now we want to recreate class by it bytes stream
unsafe X_class Creative(byte[] xobj_bytes){
 x_pointer = Memory_allocate(sizeof(X_class));//reserve an address of RAM
 write_to(x_pointer,xobj_bytes);//write bytes to RAM 
 X_class x_obj = (X_class)*(x_pointer);//recreate the class by content of pointer
 return x_obj;
}
Was it helpful?

Solution 3

While agreeing with both Jon Skeet and ValtasarIII, getting access to the raw bytes of a variable is possible (in a horrible kind of way) if your data types are structs (with known layouts), contain only value types and you're allowing unsafe code.

What follows is certainly not a technique that you'd want to use to cross machine boundaries (nor should it really be used at all).

Given a structure called TestStruct defined like so

[StructLayout(LayoutKind.Sequential)]
public struct TestStruct
{
    public int A;
    public int B;
}

The raw bytes of its contents may be obtained like this

private static unsafe byte[] GetBytes(TestStruct item)
{
    //Figure out how big TestStruct is
    var size = Marshal.SizeOf(item);
    //Make an array large enough to hold all the bytes required
    var array = new byte[size];
    //Get a pointer to the struct
    var itemPtr = &item;
    //Change the type of the pointer from TestStruct* to byte*
    var itemBytes = (byte*) itemPtr;

    //Iterate from the first byte in the data to the last, copying the values into our
    //    temporary storage
    for (var i = 0; i < size; ++i)
    {
        array[i] = itemBytes[i];
    }

    //Return the bytes that were found in the instance of TestStruct
    return array;
}

And we can build a new one like this

private static unsafe TestStruct Reconstitute(IList<byte> data)
{
    //Figure out how big TestStruct is
    var size = Marshal.SizeOf(typeof(TestStruct));

    //If the data we've been presented with is either too large or too small to contain
    //    the data for exactly one TestStruct instance, throw an exception
    if (data.Count != size)
    {
        throw new InvalidOperationException("Amount of data available is not the exact amount of data required to reconstitute the item");
    }

    //Make our temporary instance
    var item = new TestStruct();
    //Get a pointer to our temporary instance
    var itemPtr = &item;
    //Change the type of the pointer to byte*
    var itemBytes = (byte*) itemPtr;

    //Iterate from the first byte in the data to the last, copying the values into our
    //    temporary instance
    for (var i = 0; i < size; ++i)
    {
        itemBytes[i] = data[i];
    }

    //Return our reconstituted structure
    return item;
}

Usage:

static void Main()
{
    var test = new TestStruct
    {
        A = 1,
        B = 3
    };

    var bytes = GetBytes(test);
    var duplicate = Reconstitute(bytes);

    Console.WriteLine("Original");
    PrintObject(test, 1);

    Console.WriteLine();
    Console.WriteLine("Reconstituted");
    PrintObject(duplicate, 1);

    Console.ReadLine();
}

And, for completeness, the code for PrintObject

static void PrintObject(object instance, int initialIndentLevel)
{
    PrintObject(instance, initialIndentLevel, 4, ' ', new List<object>());
}

static void PrintObject(object instance, int level, int indentCount, char paddingChar, ICollection<object> printedObjects)
{
    if (printedObjects.Contains(instance))
    {
        return;
    }

    var tabs = "".PadLeft(level * indentCount, paddingChar);
    var instanceType = instance.GetType();
    printedObjects.Add(instance);

    foreach (var member in instanceType.GetMembers())
    {
        object value;
        try
        {
            switch (member.MemberType)
            {
                case MemberTypes.Property:
                    var property = (PropertyInfo) member;
                    value = property.GetValue(instance, null);
                    break;
                case MemberTypes.Field:
                    var field = (FieldInfo) member;
                    value = field.GetValue(instance);
                    break;
                default:
                    continue;
            }
        }
        catch
        {
            continue;
        }

        if (value == null || value.GetType().IsValueType || value.GetType().ToString() != value.ToString())
        {
            Console.WriteLine("{2}{0}: {1}", member.Name, (value ?? "(null)"), tabs);

        }
        else
        {
            var vals = value as IEnumerable;

            if (vals != null)
            {
                var index = 0;
                var indented = "".PadLeft((level + 1) * indentCount, paddingChar);
                Console.WriteLine("{2}{0}: {1}", member.Name, value, tabs);

                foreach (var val in vals)
                {
                    Console.WriteLine("{1}[{0}]:", index++, indented);
                    PrintObject(val, level + 2, indentCount, paddingChar, printedObjects);
                }

                if (index == 0)
                {
                    Console.WriteLine("{0}(No elements)", indented);
                }
            }
            else
            {
                PrintObject(value, level + 1, indentCount, paddingChar, printedObjects);
            }
        }
    }
}

OTHER TIPS

i want to access the bytes of an object in C# okey for example

You absolutely don't. Two reasons just to start with:

  • The object layout may well be different on the server and the client, particularly if one is using a 64-bit CLR and the other is using a 32-bit CLR
  • Objects contain process-specific data such as syncblocks, which you can't sensibly propagate
  • Any references on the "source" machine probably won't be valid on the "target" machine

Consider the bytes involved in this simple class:

class Foo
{
    string name;
}

The "bytes" of the data here just consist of a reference. For the purposes of this question, let's imagine that a reference is actually a simple pointer. A pointer to memory address 0x12345678 is very unlikely to refer to a string with the same contents when you've copied that address over to another process.

This kind of thing is precisely why we have serializers: taking a copy of the memory itself simply isn't good enough.

C# is not equivalent to C in terms of operating with memory.

1.Mark the class of the object with Serializable attribute.

2.Serialize to bytes:


public byte[] ObjectToByteArray(Object obj)
{
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    bf.Serialize(ms, obj);
    return ms.ToArray();
}

3.Deserialize to object:


public object BytesToObject(byte[] bytes)
{
        MemoryStream ms = new MemoryStream(bytes);
        BinaryFormatter bf= new BinaryFormatter();
        ms.Position = 0;
        return bf.Deserialize(ms);
}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top