[PERE]Cil revient avec sa question du jour, et bigrevindiou, elle est terrible!
Supposons une structure X (le choix ‘structure’ n’est pas inopiné, voir la suite du post), exposant les méthodes A(), B() et les propriétés internes C et D exposées par CProp et DProp. Nous avons donc:
[code]public struct X
{
public void A() { … }
public bool B() { … }
private int C;
private int D;
public CProp { get { ... } set { ... } }
public DProp { get { ... } set { ... } }
}[/code]
Cette structure doit avoir la possibilité d’être désérialisée/sérialisée en raw (tableau d’octets) pour être envoyé sur un stream réseau, c’est pourquoi nous utiliserons une structure au lieu d’une classe (qui n’est pas initialisée sur la heap, contrairement à la structure, comme expliqué par GloP dans un autre post sur ce forum).
Nous connaissons les MarshalAs, et LayoutKind. Ce sont deux “classes” qui servent a indiquer comment structurer les données internes de la structure lors de la désérialisation/sérialisation en raw, effectuées par les fonctions suivantes:
[code]// volé sur: http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/msg/aca6bf0fbe973b67
public static byte[] RawSerialize( object anything )
{
int rawsize = Marshal.SizeOf( anything );
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.StructureToPtr( anything, buffer, false );
byte[] rawdatas = new byte[ rawsize ];
Marshal.Copy( buffer, rawdatas, 0, rawsize );
Marshal.FreeHGlobal( buffer );
return rawdatas;
}
public static object RawDeserialize( byte[] rawdatas, Type anytype )
{
int rawsize = Marshal.SizeOf( anytype );
if( rawsize > rawdatas.Length )
return null;
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.Copy( rawdatas, 0, buffer, rawsize );
object retobj = Marshal.PtrToStructure( buffer, anytype );
Marshal.FreeHGlobal( buffer );
return retobj;
}[/code]
Notre structure devient donc:
[code][StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
public struct X
{
public void A() { … }
public bool B() { … }
[MarshalAs( UnmanagedType.I4 )]
private int C;
[MarshalAs( UnmanagedType.I4 )]
private int D;
public CProp { get { ... } set { ... } }
public DProp { get { ... } set { ... } }
}[/code]
Comme vous pouvez le constater, C et D, propriétés internes, sont “tagguées” comme nécéssitant d’être codé sous forme d’Int comportant 4 octets.
Le but est de créer une application qui garde à tout moment les mêmes propriétés pour une structure donnée X (dont je ne connais pas par avance les propriétés). Toutefois, cette classe pourrait avoir ses données “tagguées” comme l’exemple ci dessus. Par exemple:
[code][StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
public struct X
{
public void A() { … }
public bool B() { … }
[MarshalAs( UnmanagedType.I4 )]
[ReportToServer()]
private int C;
[MarshalAs( UnmanagedType.I4 )]
[ReportToServer()]
private int D;
public CProp { get { ... } set { ... } }
public DProp { get { ... } set { ... } }
}[/code]
A chaque fois que la variable C ou D serait modifiée, “quelque chose” s’occuperait de transmettre les modification de cette variable au serveur. Mes questions sont:
-
Est ce que c’est possible? (mon intuition me dit “oui”, mais je n’ai aucune idée sur comment créer ce genre de choses).
-
Comment faire pour que cela fonctionne avec n’importe quel type de variable et comment transmettre ces données au serveur (mon intuition me souffle Reflection)? Je verrais bien récupérer un “identifiant” pour la variable modifiée, stocker cet identifiant, ainsi que la variable modifiée, stocker le tout dans une structure, et l’envoyer au serveur, qui lirait l’identifiant variable, et mettrait cette variable à jour.
Ce que je ne sais pas faire:
- trouver un identifiant de la variable (grace au namespace reflection?) et le mettre dans une structure, ainsi que la valeur de cette variable et un identifiant classe auquel cette variable appartient.
- a partir d’une structure qui contient un identifiant pour la variable, un identifiant pour la classe et la valeur de cette variable, mettre à jour la bonne variable dans la bonne classe avec la bonne valeur.
- faire que les deux assertions précédentes fonctionnent pour n’importe quelle classe programmée, et pas par un vieux switch dans une fonction qui renverrait un identifiant suivant la variable affectée.