Pregunta

Dado un objeto FieldInfo y un objeto, necesito obtener la representación real de bytes del campo. Sé que el campo es int, Int32, uint, short etc.

¿Cómo puedo obtener la representación de bytes real? BinaryFormatter.Serialize no ayudará, ya que me dará más información de la que necesito (también registra el nombre del tipo, etc.). La clase Marshal no parece tener instalaciones para usar la matriz de bytes (pero tal vez me esté perdiendo algo).

Gracias

¿Fue útil?

Solución

También puede probar código como el siguiente si lo que realmente desea es transferir estructuras como una matriz de bytes:

int rawsize = Marshal.SizeOf(value);
byte[] rawdata = new byte[rawsize];
GCHandle handle = GCHandle.Alloc(rawdata, GCHandleType.Pinned);
Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(), false);
handle.Free();

Esto convierte el objeto dado valor a la matriz de bytes rawdata. Tomé esto del código que escribí anteriormente, y es posible que necesite adaptarlo a sus necesidades para que realmente funcione. Lo usé para comunicarme con algún hardware con estructuras definidas por el usuario, pero también debería funcionar para los tipos incorporados (después de todo, son estructuras, ¿no?)

Para hacer que los miembros de la estructura estén correctamente alineados, use el atributo StructLayout para especificar la alineación de un byte:

[StructLayout(LayoutKind.Sequential, Pack = 1)]

Y luego use el atributo MarshalAs según sea necesario para los campos, por ejemplo, para matrices en línea:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
byte[] _state;

El código para recuperar la estructura de la matriz de bytes es algo como esto:

public T GetValue<T>()
{
    GCHandle handle = GCHandle.Alloc(RawValue, GCHandleType.Pinned);
    T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), 
                      typeof(T));
    handle.Free();
    return structure;
}

Por supuesto que necesitará saber el tipo que desea para que esto funcione.

Tenga en cuenta que esto no manejará el endianness por sí mismo. En mi proyecto, la mayoría de los campos solo tenían un byte, por lo que no importaba, pero para los pocos campos en los que lo hacía, simplemente los convertía en privados y agregaba propiedades públicas que se encargarían de la endianidad ( El enlace de Jon Skeet de un comentario a su respuesta puede ayudarlo, escribí algunas funciones de utilidad para esto ya que solo necesitaba pocos).

Cuando necesité esto, creé una clase de Mensaje que almacenaría el valor sin procesar (de ahí el método GetValue, el código en la parte superior es en realidad el cuerpo de un método SetValue) y tuve un buen método de conveniencia para obtener el valor formateado etc.

Otros consejos

Use BitConverter.GetBytes ()

Primero tendrás que convertir el valor a su tipo nativo, luego usar BitConverter para obtener los bytes:

byte[] Bytes;

if (valType == typeof(int))
{
    int intVal = (int) GetFieldValue(....);
    Bytes = BitConverter.GetBytes(intVval);
} 
else if (valType == typeof(long))
{
    int lngVal = (long) GetFieldValue(....);
    Bytes = BitConverter.GetBytes(lngVal);
} else ....

¿Te refieres a la representación definitiva en memoria? BitConverter.GetBytes (con una sobrecarga elegida adecuadamente por reflexión) le devolverá una representación de byte a , pero no necesariamente lo que está actualmente en la memoria.

Tal vez si proporciona más información sobre por qué quiere esto, podremos ayudarlo mejor.

EDITAR: Debo agregar que, en cualquier caso razonable que se me ocurra, BitConverter le dará la misma representación que en la memoria, pero puede haber situaciones extrañas relacionadas con la endianidad y posiblemente arquitecturas extrañas con diferentes Representaciones de punto flotante que podrían dar resultados extraños.

EDITAR: Este es un programa de ejemplo completo que muestra cómo podría hacerlo:

using System;
using System.Reflection;

public class Test
{
    public int x = 300;

    static void Main()
    {
        Test instance = new Test();
        FieldInfo field = typeof(Test).GetField("x");

        MethodInfo converter = typeof(BitConverter).GetMethod("GetBytes", 
            new Type[] {field.FieldType});

        if (converter == null)
        {
            Console.WriteLine("No BitConverter.GetBytes method found for type "
                + field.FieldType);            
        }
        else
        {
            byte[] bytes = (byte[]) converter.Invoke(null,
                new object[] {field.GetValue(instance) });
            Console.WriteLine("Byte array: {0}", BitConverter.ToString(bytes));
        }        
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top