Pergunta

Dado um objeto FieldInfo e um objeto, eu preciso para obter a representação bytes real do campo. Eu sei que o campo é ou int,Int32,uint,short etc.

Como posso obter a representação real de bytes? BinaryFormatter.Serialize não vai ajudar, uma vez que vai me dar mais informações do que eu preciso (que também registra nome de tipo etc.). A classe Marshal não parecem ter instalações para uso bytes array (mas talvez eu estou faltando alguma coisa).

Graças

Foi útil?

Solução

Você também pode tentar um código como o seguinte, se o que você realmente quer é estruturas de transferência como uma 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();

Isso converte o objeto dado valor para o rawData matriz de bytes. Eu tenho tomado isto de código que eu escrevi anteriormente, e pode ser necessário adaptá-lo às suas necessidades para torná-lo realmente funcionar. Usei-o para a comunicação com algum hardware com estruturas definidas pelo usuário, mas ele deve trabalhar para built-in tipos, bem como (, eles são estruturas afinal, não são eles?)

Para tornar a estrutura membros adequadamente alinhado, usar o atributo StructLayout para especificar um byte-alinhamento:

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

E, em seguida, usar o atributo MarshalAs conforme necessário para os campos, por exemplo, para matrizes em linha:

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

O código para obter a estrutura de volta da matriz de bytes é algo como isto:

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

É claro que você precisa saber o tipo que você deseja para que isso funcione.

Note que isso não vai lidar com endianness por si. No meu projeto, a maioria dos campos eram apenas um byte, por isso não tinha importância, mas para os poucos campos em que ele fez, eu fiz apenas os campos privado e acrescentou propriedades públicas que cuidam da endianness ( link de Jon Skeet de um comentário à sua resposta pode ajudá-lo, eu escrevi algumas funções utilitárias para isso desde que eu precisava única alguns).

Quando eu precisava disso, eu criei uma classe de mensagem que iria armazenar o valor bruto (daí o método GetValue, o código no topo é realmente o corpo de um método SetValue) e teve algum método conveniência agradável para obter o valor formatado etc.

Outras dicas

Use BitConverter.GetBytes ()

Você primeiro tem que converter o valor em que é tipo nativo, do que o uso BitConverter para obter os 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 ....

Você quer dizer a representação definitiva na memória? BitConverter.GetBytes (com uma sobrecarga convenientemente escolhido pela reflexão) irá retornar a representação byte, mas não necessariamente o que está atualmente na memória.

Talvez se você dar mais informações sobre por que você quer isso, nós vamos ser mais capazes de ajudá-lo.

EDIT: Devo acrescentar que, em qualquer caso sensível que eu posso pensar, BitConverter irá dar-lhe a mesma representação como na memória - mas pode haver situações estranhas envolvendo endianness e arquiteturas possivelmente estranhos com diferentes representações de ponto flutuante que poderia dar resultados estranhos.

EDIT: Aqui está uma demonstração completa programa de exemplo como você pode ir sobre ele:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top