2010-09-30 24 views
0

Pour des raisons de test, je souhaite comparer deux structures (de type T inconnu) marshalées à partir de code non géré.Comparaison par champs de la structure non managée

Parce qu'ils peuvent contenir une garniture dans la représentation non géré, il est inapproprié de convertir struct tout au tableau d'octets et comparer octet par octet:

int  size = Marshal.SizeOf(typeof(T)); 
IntPtr buf1 = Marshal.AllocHGlobal(size); // FreeHGlobal omitted for simplicity 
IntPtr buf2 = Marshal.AllocHGlobal(size); 
byte[] array1 = new byte[size]; 
byte[] array2 = new byte[size]; 
Marshal.StructureToPtr(st1, buf1, false); 
Marshal.StructureToPtr(st2, buf2, false); 
Marshal.Copy(buf1, array1, 0, size); 
Marshal.Copy(buf2, array2, 0, size); 

// inapropriate 
for (int i = 0; i < size; ++i) 
{ 
    if (array1[i] != array2[i]) { return false; } 
} 
return true; 

Je pense qu'il est nécessaire de comparer champ par champ.

Merci à la réflexion, je peux énumérer FieldInfo, puis en utilisant la méthode Marshal.OffsetOf, je peux obtenir des offsets des champs.

Malheureusement, je ne sais pas comment obtenir la taille des champs. Sans cela, je pense que je ne peux pas comparer deux domaines en éliminant l'effet de l'emballage.

foreach (var fieldInfo in typeof(T).GetFields()) 
{ 
    int offset  = (int)Marshal.OffsetOf(typeof(T), fieldInfo.Name); 
    int fieldSize = ...;  // I need this 
    for (int i = offset; i < offset + fieldSize; ++i) 
    { 
     if (array1[i] != array2[i]) { return false; } 
    } 
} 
return true; 

Y at-il un moyen d'accomplir cela? Ou Y a-t-il une meilleure façon de comparer les structures non gérées?

Note: types de terrain sont arbitraires (peut être des nombres entiers primitifs, les tableaux, les chaînes, les énumérations, struct, etc.).

Répondre

0

Pouvez-vous utiliser Marshal.SizeOf(fieldInfo.FieldType)?

De plus, les deux structures pourraient-elles être emballées différemment? Parce que s'ils ne le sont pas, l'emballage ne devient-il pas inutile? Pouvez-vous donner un exemple d'où l'emballage signifie qu'une comparaison directe octet par octet vous donne la mauvaise réponse? Je suppose que lorsque la mémoire est allouée, elle est mise à zéro - donc tous les octets inutilisés (en raison du remplissage) seront nuls et donc égaux dans les deux tableaux.