a obtenção de um / curto de bytes / representação byte estrutura Int com C #
-
03-07-2019 - |
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
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));
}
}
}