J'ai enfin trouv� o� �tait cach� ce satan� FieldOffset dans l'objet RtFieldInfo.
Pour ce faire j'ai mis un data break point sur l'adresse d'un champ, puis j'ai appel� Field.SetValue, �a m'a amen� au code assembleur de clr.dll et au champ non typ� RuntimeFieldHandle.m_ptr
(clr.dll c'est du code non manag� mais heureusement ils ont laiss� dans le .pdb les noms des fonctions)
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
// RuntimeFieldHandle.cpp : main project file.
 
#include "stdafx.h"
 
using namespace System;
using namespace System::Reflection;
 
// Je définis un type .NET avec plein de champs, 
// et je retrouve bien l'offset 28 (en 32bit) pour le champ String ^s
 
ref struct A {
	Object ^h;
	Int32 ^k,^l,^m,pp;
	UInt32 a,b,c,d,e;
	Object ^h2;
private :
	Type ^t;
	Boolean p;
	UInt32 a2,b2,c2,d2,e2;
public:
	String ^s;
};
 
generic <typename T> value struct FieldReference {
	UInt32 offset;
	Object ^obj;
 
	value struct RuntimeFieldHandle_m_ptr {
		UInt32 a,b,offset; // attention UInt32 est peut-être uniquement valable en 32bit
	};
 
	static UInt32 GetFieldOffset(FieldInfo ^f) {
		RuntimeFieldHandle h = f->FieldHandle;
		IntPtr value = h.Value;
		RuntimeFieldHandle_m_ptr * m_ptr = (RuntimeFieldHandle_m_ptr *)(void*)value; // le type de value n'est pas communiqué par .NET : il faut le trouver soi-même
		UInt32 res = m_ptr->offset;
                // le premier bit est probablement un flag ?
		res &= 0x7FFFFFF; // attention 0x7FFFFFF est peut-être uniquement valable en 32bit
 
		return res +  sizeof(void*); // ajout de la VMT
	}
 
 
	FieldReference(Object ^obj, UInt32 offset) : obj(obj), offset(offset) {}
 
	FieldReference(Object ^obj, FieldInfo^ fi) : obj(obj) {
		offset = GetFieldOffset(fi);
	}
 
	FieldReference(Object ^obj, String ^fieldName) : obj(obj) {
		Type ^t = obj->GetType();
		FieldInfo ^fi = t->GetField(fieldName);
		offset = GetFieldOffset(fi);
	}
 
	property T Value {
 
		T get() {
			pin_ptr<Object^> tmp = &this->obj;
			void *ptr = (void*)tmp;
			char *objadr = *(char**)ptr;
			void *fieldadr = objadr + this->offset;
 
			return (T)*(Object^*)fieldadr;
		}
		void set(T t) {
			pin_ptr<Object^> tmp = &this->obj;
			void *ptr = (void*)tmp;
			char *objadr = *(char**)ptr;
			void *fieldadr = objadr + this->offset;
 
			*(Object^*)fieldadr = t;
		}
	};
};
 
int main(array<System::String ^> ^args)
{
	A ^a = gcnew A();
	a->s = "avant";
 
	FieldReference<String^> a_s(a,"s");
	a_s.Value = "apres";
	Console::WriteLine(a->s);
    return 0;
}
Je n'ai pas test� en 64 bit : la constante 0x7FFFFFF et les UInt32 de RuntimeFieldHandle_m_ptr deviennent peut-�tre des UInt64.