Search code examples
c#memory-access

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


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;
}

Solution

  • 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);
                }
            }
        }
    }