5 // Jb Evain (jbevain@gmail.com)
8 // (C) 2006 Evaluant RC S.A.
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 namespace Mono.Cecil {
34 using System.Collections;
35 using SR = System.Reflection;
38 internal sealed class ReflectionHelper {
40 ModuleDefinition m_module;
42 public ReflectionHelper (ModuleDefinition module)
47 public AssemblyNameReference ImportAssembly (SR.Assembly asm)
49 AssemblyNameReference asmRef = GetAssemblyNameReference (asm.GetName ());
53 SR.AssemblyName asmName = asm.GetName ();
54 asmRef = new AssemblyNameReference (
55 asmName.Name, asmName.CultureInfo.Name, asmName.Version);
56 asmRef.PublicKeyToken = asmName.GetPublicKeyToken ();
57 asmRef.HashAlgorithm = (AssemblyHashAlgorithm) asmName.HashAlgorithm;
58 asmRef.Culture = asmName.CultureInfo.ToString ();
59 m_module.AssemblyReferences.Add (asmRef);
63 AssemblyNameReference GetAssemblyNameReference (SR.AssemblyName name)
65 foreach (AssemblyNameReference reference in m_module.AssemblyReferences)
66 if (reference.FullName == name.FullName)
72 public static string GetTypeSignature (Type t)
74 if (t.HasElementType) {
76 return string.Concat (GetTypeSignature (t.GetElementType ()), "*");
78 int rank = t.GetArrayRank ();
80 return string.Concat (GetTypeSignature (t.GetElementType ()), "[]");
82 StringBuilder sb = new StringBuilder ();
84 for (int i = 1; i < rank; i++)
88 return string.Concat (GetTypeSignature (t.GetElementType ()), sb.ToString ());
90 return string.Concat(GetTypeSignature(t.GetElementType()), "&");
93 if (IsGenericTypeSpec (t)) {
94 StringBuilder sb = new StringBuilder ();
95 sb.Append (GetTypeSignature (GetGenericTypeDefinition (t)));
97 Type [] genArgs = GetGenericArguments (t);
98 for (int i = 0; i < genArgs.Length; i++) {
101 sb.Append (GetTypeSignature (genArgs [i]));
104 return sb.ToString ();
107 if (IsGenericParameter (t))
110 if (t.DeclaringType != null)
111 return string.Concat (t.DeclaringType.FullName, "/", t.Name);
113 if (t.Namespace == null || t.Namespace.Length == 0)
116 return string.Concat (t.Namespace, ".", t.Name);
119 static bool GetProperty (object o, string prop)
121 SR.PropertyInfo pi = o.GetType ().GetProperty (prop);
125 return (bool) pi.GetValue (o, null);
128 public static bool IsGenericType (Type t)
130 return GetProperty (t, "IsGenericType");
133 static bool IsGenericParameter (Type t)
135 return GetProperty (t, "IsGenericParameter");
138 static bool IsGenericTypeDefinition (Type t)
140 return GetProperty (t, "IsGenericTypeDefinition");
143 static bool IsGenericTypeSpec (Type t)
145 return IsGenericType (t) && !IsGenericTypeDefinition (t);
148 static Type GetGenericTypeDefinition (Type t)
150 return (Type) t.GetType ().GetMethod ("GetGenericTypeDefinition").Invoke (t, null);
153 static Type [] GetGenericArguments (Type t)
155 return (Type []) t.GetType ().GetMethod ("GetGenericArguments").Invoke (t, null);
158 GenericInstanceType GetGenericType (Type t, TypeReference element, ImportContext context)
160 GenericInstanceType git = new GenericInstanceType (element);
161 foreach (Type genArg in GetGenericArguments (t))
162 git.GenericArguments.Add (ImportSystemType (genArg, context));
167 static bool GenericParameterOfMethod (Type t)
169 return t.GetType ().GetProperty ("DeclaringMethod").GetValue (t, null) != null;
172 static GenericParameter GetGenericParameter (Type t, ImportContext context)
174 int pos = (int) t.GetType ().GetProperty ("GenericParameterPosition").GetValue (t, null);
175 if (GenericParameterOfMethod (t))
176 return context.GenericContext.Method.GenericParameters [pos];
178 return context.GenericContext.Type.GenericParameters [pos];
181 TypeReference GetTypeSpec (Type t, ImportContext context)
183 Stack s = new Stack ();
184 while (t.HasElementType || IsGenericTypeSpec (t)) {
186 if (t.HasElementType)
187 t = t.GetElementType ();
188 else if (IsGenericTypeSpec (t)) {
189 t = (Type) t.GetType ().GetMethod ("GetGenericTypeDefinition").Invoke (t, null);
194 TypeReference elementType = ImportSystemType (t, context);
195 while (s.Count > 0) {
198 elementType = new PointerType (elementType);
200 elementType = new ArrayType (elementType, t.GetArrayRank ());
202 elementType = new ReferenceType (elementType);
203 else if (IsGenericTypeSpec (t))
204 elementType = GetGenericType (t, elementType, context);
206 throw new ReflectionException ("Unknown element type");
212 public TypeReference ImportSystemType (Type t, ImportContext context)
214 if (t.HasElementType || IsGenericTypeSpec (t))
215 return GetTypeSpec (t, context);
217 if (IsGenericParameter (t))
218 return GetGenericParameter (t, context);
220 TypeReference type = m_module.TypeReferences [GetTypeSignature (t)];
222 if (t.IsValueType && !type.IsValueType)
223 type.IsValueType = true;
228 AssemblyNameReference asm = ImportAssembly (t.Assembly);
229 if (t.DeclaringType != null) {
230 type = new TypeReference (t.Name, string.Empty, asm, t.IsValueType);
231 type.DeclaringType = ImportSystemType (t.DeclaringType, context);
233 type = new TypeReference (t.Name, t.Namespace, asm, t.IsValueType);
235 if (IsGenericTypeDefinition (t))
236 foreach (Type genParam in GetGenericArguments (t))
237 type.GenericParameters.Add (new GenericParameter (genParam.Name, type));
239 context.GenericContext.Type = type;
241 m_module.TypeReferences.Add (type);
245 static string GetMethodBaseSignature (SR.MethodBase meth, Type declaringType, Type retType)
247 StringBuilder sb = new StringBuilder ();
248 sb.Append (GetTypeSignature (retType));
250 sb.Append (GetTypeSignature (declaringType));
252 sb.Append (meth.Name);
253 if (IsGenericMethodSpec (meth)) {
255 Type [] genArgs = GetGenericArguments (meth as SR.MethodInfo);
256 for (int i = 0; i < genArgs.Length; i++) {
259 sb.Append (GetTypeSignature (genArgs [i]));
264 SR.ParameterInfo [] parameters = meth.GetParameters ();
265 for (int i = 0; i < parameters.Length; i++) {
268 sb.Append (GetTypeSignature (parameters [i].ParameterType));
271 return sb.ToString ();
274 static bool IsGenericMethod (SR.MethodBase mb)
276 return GetProperty (mb, "IsGenericMethod");
279 static bool IsGenericMethodDefinition (SR.MethodBase mb)
281 return GetProperty (mb, "IsGenericMethodDefinition");
284 static bool IsGenericMethodSpec (SR.MethodBase mb)
286 return IsGenericMethod (mb) && !IsGenericMethodDefinition (mb);
289 static Type [] GetGenericArguments (SR.MethodInfo mi)
291 return (Type []) mi.GetType ().GetMethod ("GetGenericArguments").Invoke (mi, null);
294 static int GetMetadataToken (SR.MethodInfo mi)
296 return (int) mi.GetType ().GetProperty ("MetadataToken").GetValue (mi, null);
299 MethodReference ImportGenericInstanceMethod (SR.MethodInfo mi, ImportContext context)
301 SR.MethodInfo gmd = (SR.MethodInfo) mi.GetType ().GetMethod ("GetGenericMethodDefinition").Invoke (mi, null);
302 GenericInstanceMethod gim = new GenericInstanceMethod (
303 ImportMethodBase (gmd, gmd.ReturnType, context));
305 foreach (Type genArg in GetGenericArguments (mi))
306 gim.GenericArguments.Add (ImportSystemType (genArg, context));
311 MethodReference ImportMethodBase (SR.MethodBase mb, Type retType, ImportContext context)
313 if (IsGenericMethod (mb) && !IsGenericMethodDefinition (mb))
314 return ImportGenericInstanceMethod ((SR.MethodInfo) mb, context);
316 Type originalDecType = mb.DeclaringType;
317 Type declaringTypeDef = originalDecType;
318 while (IsGenericTypeSpec (declaringTypeDef))
319 declaringTypeDef = GetGenericTypeDefinition (declaringTypeDef);
321 if (mb.DeclaringType != declaringTypeDef && mb is SR.MethodInfo) {
322 int mt = GetMetadataToken (mb as SR.MethodInfo);
323 // hack to get the generic method definition from the constructed method
324 foreach (SR.MethodInfo mi in declaringTypeDef.GetMethods ()) {
325 if (GetMetadataToken (mi) == mt) {
327 retType = mi.ReturnType;
333 string sig = GetMethodBaseSignature (mb, originalDecType, retType);
334 MethodReference meth = (MethodReference) GetMemberReference (sig);
338 meth = new MethodReference (
340 (mb.CallingConvention & SR.CallingConventions.HasThis) > 0,
341 (mb.CallingConvention & SR.CallingConventions.ExplicitThis) > 0,
342 MethodCallingConvention.Default); // TODO: get the real callconv
343 meth.DeclaringType = ImportSystemType (originalDecType, context);
345 if (IsGenericMethod (mb))
346 foreach (Type genParam in GetGenericArguments (mb as SR.MethodInfo))
347 meth.GenericParameters.Add (new GenericParameter (genParam.Name, meth));
349 TypeReference contextType = context.GenericContext.Type;
350 MethodReference contextMethod = context.GenericContext.Method;
352 context.GenericContext.Method = meth;
353 context.GenericContext.Type = ImportSystemType (declaringTypeDef, context);
355 meth.ReturnType.ReturnType = ImportSystemType (retType, context);
357 SR.ParameterInfo [] parameters = mb.GetParameters ();
358 for (int i = 0; i < parameters.Length; i++)
359 meth.Parameters.Add (new ParameterDefinition (
360 ImportSystemType (parameters [i].ParameterType, context)));
362 context.GenericContext.Type = contextType;
363 context.GenericContext.Method = contextMethod;
365 m_module.MemberReferences.Add (meth);
369 public MethodReference ImportConstructorInfo (SR.ConstructorInfo ci, ImportContext context)
371 return ImportMethodBase (ci, typeof (void), context);
374 public MethodReference ImportMethodInfo (SR.MethodInfo mi, ImportContext context)
376 return ImportMethodBase (mi, mi.ReturnType, context);
379 static string GetFieldSignature (SR.FieldInfo field)
381 StringBuilder sb = new StringBuilder ();
382 sb.Append (GetTypeSignature (field.FieldType));
384 sb.Append (GetTypeSignature (field.DeclaringType));
386 sb.Append (field.Name);
387 return sb.ToString ();
390 public FieldReference ImportFieldInfo (SR.FieldInfo fi, ImportContext context)
392 string sig = GetFieldSignature (fi);
393 FieldReference f = (FieldReference) GetMemberReference (sig);
397 f = new FieldReference (
399 ImportSystemType (fi.DeclaringType, context),
400 ImportSystemType (fi.FieldType, context));
402 m_module.MemberReferences.Add (f);
406 MemberReference GetMemberReference (string signature)
408 foreach (MemberReference reference in m_module.MemberReferences)
409 if (reference.ToString () == signature)