2 Copyright (C) 2009-2012 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Collections.Generic;
27 using IKVM.Reflection.Metadata;
29 namespace IKVM.Reflection.Reader
31 sealed class MethodDefImpl : MethodInfo
33 private readonly ModuleReader module;
34 private readonly int index;
35 private readonly TypeDefImpl declaringType;
36 private MethodSignature lazyMethodSignature;
37 private ParameterInfo returnParameter;
38 private ParameterInfo[] parameters;
39 private Type[] typeArgs;
41 internal MethodDefImpl(ModuleReader module, TypeDefImpl declaringType, int index)
45 this.declaringType = declaringType;
48 public override MethodBody GetMethodBody()
50 return GetMethodBody(this);
53 internal MethodBody GetMethodBody(IGenericContext context)
55 if ((GetMethodImplementationFlags() & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL)
60 int rva = module.MethodDef.records[index].RVA;
61 return rva == 0 ? null : new MethodBody(module, rva, context);
64 public override int __MethodRVA
66 get { return module.MethodDef.records[index].RVA; }
69 public override CallingConventions CallingConvention
71 get { return this.MethodSignature.CallingConvention; }
74 public override MethodAttributes Attributes
76 get { return (MethodAttributes)module.MethodDef.records[index].Flags; }
79 public override MethodImplAttributes GetMethodImplementationFlags()
81 return (MethodImplAttributes)module.MethodDef.records[index].ImplFlags;
84 public override ParameterInfo[] GetParameters()
87 return (ParameterInfo[])parameters.Clone();
90 private void PopulateParameters()
92 if (parameters == null)
94 MethodSignature methodSignature = this.MethodSignature;
95 parameters = new ParameterInfo[methodSignature.GetParameterCount()];
96 int parameter = module.MethodDef.records[index].ParamList - 1;
97 int end = module.MethodDef.records.Length > index + 1 ? module.MethodDef.records[index + 1].ParamList - 1 : module.Param.records.Length;
98 for (; parameter < end; parameter++)
100 int seq = module.Param.records[parameter].Sequence - 1;
103 returnParameter = new ParameterInfoImpl(this, seq, parameter);
107 parameters[seq] = new ParameterInfoImpl(this, seq, parameter);
110 for (int i = 0; i < parameters.Length; i++)
112 if (parameters[i] == null)
114 parameters[i] = new ParameterInfoImpl(this, i, -1);
117 if (returnParameter == null)
119 returnParameter = new ParameterInfoImpl(this, -1, -1);
124 internal override int ParameterCount
126 get { return this.MethodSignature.GetParameterCount(); }
129 public override ParameterInfo ReturnParameter
133 PopulateParameters();
134 return returnParameter;
138 public override Type ReturnType
142 return this.ReturnParameter.ParameterType;
146 public override Type DeclaringType
148 get { return declaringType.IsModulePseudoType ? null : declaringType; }
151 public override string Name
153 get { return module.GetString(module.MethodDef.records[index].Name); }
156 public override int MetadataToken
158 get { return (MethodDefTable.Index << 24) + index + 1; }
161 public override bool IsGenericMethodDefinition
165 PopulateGenericArguments();
166 return typeArgs.Length > 0;
170 public override bool IsGenericMethod
172 get { return IsGenericMethodDefinition; }
175 public override Type[] GetGenericArguments()
177 PopulateGenericArguments();
178 return Util.Copy(typeArgs);
181 private void PopulateGenericArguments()
183 if (typeArgs == null)
185 int token = this.MetadataToken;
186 int first = module.GenericParam.FindFirstByOwner(token);
189 typeArgs = Type.EmptyTypes;
193 List<Type> list = new List<Type>();
194 int len = module.GenericParam.records.Length;
195 for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
197 list.Add(new GenericTypeParameter(module, i));
199 typeArgs = list.ToArray();
204 internal override Type GetGenericMethodArgument(int index)
206 PopulateGenericArguments();
207 return typeArgs[index];
210 internal override int GetGenericMethodArgumentCount()
212 PopulateGenericArguments();
213 return typeArgs.Length;
216 public override MethodInfo GetGenericMethodDefinition()
218 if (this.IsGenericMethodDefinition)
222 throw new InvalidOperationException();
225 public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
227 return new GenericMethodInstance(declaringType, this, typeArguments);
230 public override Module Module
232 get { return module; }
235 internal override MethodSignature MethodSignature
237 get { return lazyMethodSignature ?? (lazyMethodSignature = MethodSignature.ReadSig(module, module.GetBlob(module.MethodDef.records[index].Signature), this)); }
240 internal override int ImportTo(Emit.ModuleBuilder module)
242 return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature);
245 public override MethodInfo[] __GetMethodImpls()
247 Type[] typeArgs = null;
248 List<MethodInfo> list = null;
249 foreach (int i in module.MethodImpl.Filter(declaringType.MetadataToken))
251 if (module.MethodImpl.records[i].MethodBody == this.MetadataToken)
253 if (typeArgs == null)
255 typeArgs = declaringType.GetGenericArguments();
259 list = new List<MethodInfo>();
261 list.Add((MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null));
264 return Util.ToArray(list, Empty<MethodInfo>.Array);
267 internal override int GetCurrentToken()
269 return this.MetadataToken;
272 internal override bool IsBaked
278 sealed class ParameterInfoImpl : ParameterInfo
280 private readonly MethodDefImpl method;
281 private readonly int position;
282 private readonly int index;
284 internal ParameterInfoImpl(MethodDefImpl method, int position, int index)
286 this.method = method;
287 this.position = position;
291 public override string Name
293 get { return index == -1 ? null : ((ModuleReader)this.Module).GetString(this.Module.Param.records[index].Name); }
296 public override Type ParameterType
298 get { return position == -1 ? method.MethodSignature.GetReturnType(method) : method.MethodSignature.GetParameterType(method, position); }
301 public override ParameterAttributes Attributes
303 get { return index == -1 ? ParameterAttributes.None : (ParameterAttributes)this.Module.Param.records[index].Flags; }
306 public override int Position
308 get { return position; }
311 public override object RawDefaultValue
315 if ((this.Attributes & ParameterAttributes.HasDefault) != 0)
317 return this.Module.Constant.GetRawConstantValue(this.Module, this.MetadataToken);
319 Universe universe = this.Module.universe;
320 if (this.ParameterType == universe.System_Decimal)
322 Type attr = universe.System_Runtime_CompilerServices_DecimalConstantAttribute;
325 foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(this, attr, false))
327 IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
330 if (args[0].ArgumentType == universe.System_Byte
331 && args[1].ArgumentType == universe.System_Byte
332 && args[2].ArgumentType == universe.System_Int32
333 && args[3].ArgumentType == universe.System_Int32
334 && args[4].ArgumentType == universe.System_Int32)
336 return new Decimal((int)args[4].Value, (int)args[3].Value, (int)args[2].Value, (byte)args[1].Value != 0, (byte)args[0].Value);
338 else if (args[0].ArgumentType == universe.System_Byte
339 && args[1].ArgumentType == universe.System_Byte
340 && args[2].ArgumentType == universe.System_UInt32
341 && args[3].ArgumentType == universe.System_UInt32
342 && args[4].ArgumentType == universe.System_UInt32)
344 return new Decimal(unchecked((int)(uint)args[4].Value), unchecked((int)(uint)args[3].Value), unchecked((int)(uint)args[2].Value), (byte)args[1].Value != 0, (byte)args[0].Value);
350 if ((this.Attributes & ParameterAttributes.Optional) != 0)
352 return Missing.Value;
358 public override CustomModifiers __GetCustomModifiers()
360 return position == -1
361 ? method.MethodSignature.GetReturnTypeCustomModifiers(method)
362 : method.MethodSignature.GetParameterCustomModifiers(method, position);
365 public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal)
367 return FieldMarshal.ReadFieldMarshal(this.Module, this.MetadataToken, out fieldMarshal);
370 public override MemberInfo Member
374 // return the right ConstructorInfo wrapper
375 return method.Module.ResolveMethod(method.MetadataToken);
379 public override int MetadataToken
383 // for parameters that don't have a row in the Param table, we return 0x08000000 (because index is -1 in that case),
385 return (ParamTable.Index << 24) + index + 1;
389 internal override Module Module
391 get { return method.Module; }