0

我想在 C# okey 中访问对象的字节,例如:

在 WCF 中序列化一个类,序列化程序读取类对象的所有字节,最后是 SOAP 消息!

像这样的事情你知道一种读取对象字节并通过其字节重新创建对象的方法

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

3 回答 3

5

例如,我想在 C# okey 中访问对象的字节

你绝对没有。刚开始的两个原因:

  • 服务器和客户端上的对象布局很可能不同,特别是如果一个使用 64 位 CLR 而另一个使用 32 位 CLR
  • 对象包含特定于进程的数据,例如同步块,您无法合理地传播这些数据
  • “源”机器上的任何引用都可能在“目标”机器上无效

考虑这个简单类中涉及的字节:

class Foo
{
    string name;
}

这里数据的“字节”只包含一个引用。出于这个问题的目的,让我们假设一个引用实际上是一个简单的指针。当您将该地址复制到另一个进程时,指向内存地址 0x12345678 的指针不太可能引用具有相同内容的字符串。

这种事情正是我们有序列化程序的原因:获取内存本身的副本根本不够好。

于 2012-11-28T09:28:20.513 回答
2

C# 在内存操作方面并不等同于 C。

1.用Serializable属性标记对象的类。

2.序列化为字节:


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

3.反序列化为对象:


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

于 2012-11-28T09:39:56.953 回答
1

虽然同意 Jon Skeet 和 ValtasarIII,但如果您的数据类型是结构(具有已知布局)、仅包含值类型并且您允许unsafe代码,则可以(以一种可怕的方式)访问变量的原始字节.

接下来的内容当然不是您想要用来跨越机器边界的技术(也不应该真正使用它)。

给定一个名为TestStructdefined的结构,如下所示

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

可以像这样获得其内容的原始字节

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

我们可以像这样建造一个新的

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

用法:

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

并且,为了完整起见,代码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);
            }
        }
    }
}
于 2012-11-28T10:33:16.347 回答