2 Copyright (C) 2009-2011 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 System.Runtime.InteropServices;
28 using IKVM.Reflection.Metadata;
30 namespace IKVM.Reflection.Reader
32 sealed class TypeDefImpl : TypeInfo
34 private readonly ModuleReader module;
35 private readonly int index;
36 private readonly string typeName;
37 private readonly string typeNamespace;
38 private Type[] typeArgs;
40 internal TypeDefImpl(ModuleReader module, int index)
44 this.typeName = module.GetString(module.TypeDef.records[index].TypeName);
45 this.typeNamespace = module.GetString(module.TypeDef.records[index].TypeNamespace);
46 MarkEnumOrValueType(typeNamespace, typeName);
49 public override Type BaseType
53 int extends = module.TypeDef.records[index].Extends;
54 if ((extends & 0xFFFFFF) == 0)
58 return module.ResolveType(extends, this);
62 public override TypeAttributes Attributes
64 get { return (TypeAttributes)module.TypeDef.records[index].Flags; }
67 public override EventInfo[] __GetDeclaredEvents()
69 foreach (int i in module.EventMap.Filter(this.MetadataToken))
71 int evt = module.EventMap.records[i].EventList - 1;
72 int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length;
73 EventInfo[] events = new EventInfo[end - evt];
74 if (module.EventPtr.RowCount == 0)
76 for (int j = 0; evt < end; evt++, j++)
78 events[j] = new EventInfoImpl(module, this, evt);
83 for (int j = 0; evt < end; evt++, j++)
85 events[j] = new EventInfoImpl(module, this, module.EventPtr.records[evt] - 1);
90 return Empty<EventInfo>.Array;
93 public override FieldInfo[] __GetDeclaredFields()
95 int field = module.TypeDef.records[index].FieldList - 1;
96 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length;
97 FieldInfo[] fields = new FieldInfo[end - field];
98 if (module.FieldPtr.RowCount == 0)
100 for (int i = 0; field < end; i++, field++)
102 fields[i] = module.GetFieldAt(this, field);
107 for (int i = 0; field < end; i++, field++)
109 fields[i] = module.GetFieldAt(this, module.FieldPtr.records[field] - 1);
115 public override Type[] __GetDeclaredInterfaces()
117 List<Type> list = null;
118 foreach (int i in module.InterfaceImpl.Filter(this.MetadataToken))
122 list = new List<Type>();
124 list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
126 return Util.ToArray(list, Type.EmptyTypes);
129 public override MethodBase[] __GetDeclaredMethods()
131 int method = module.TypeDef.records[index].MethodList - 1;
132 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
133 MethodBase[] methods = new MethodBase[end - method];
134 if (module.MethodPtr.RowCount == 0)
136 for (int i = 0; method < end; method++, i++)
138 methods[i] = module.GetMethodAt(this, method);
143 for (int i = 0; method < end; method++, i++)
145 methods[i] = module.GetMethodAt(this, module.MethodPtr.records[method] - 1);
151 public override __MethodImplMap __GetMethodImplMap()
153 PopulateGenericArguments();
154 List<MethodInfo> bodies = new List<MethodInfo>();
155 List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
156 foreach (int i in module.MethodImpl.Filter(this.MetadataToken))
158 MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
159 int index = bodies.IndexOf(body);
162 index = bodies.Count;
164 declarations.Add(new List<MethodInfo>());
166 MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
167 declarations[index].Add(declaration);
169 __MethodImplMap map = new __MethodImplMap();
170 map.TargetType = this;
171 map.MethodBodies = bodies.ToArray();
172 map.MethodDeclarations = new MethodInfo[declarations.Count][];
173 for (int i = 0; i < map.MethodDeclarations.Length; i++)
175 map.MethodDeclarations[i] = declarations[i].ToArray();
180 public override Type[] __GetDeclaredTypes()
182 int token = this.MetadataToken;
183 List<Type> list = new List<Type>();
184 // note that the NestedClass table is sorted on NestedClass, so we can't use binary search
185 for (int i = 0; i < module.NestedClass.records.Length; i++)
187 if (module.NestedClass.records[i].EnclosingClass == token)
189 list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
192 return list.ToArray();
195 public override PropertyInfo[] __GetDeclaredProperties()
197 foreach (int i in module.PropertyMap.Filter(this.MetadataToken))
199 int property = module.PropertyMap.records[i].PropertyList - 1;
200 int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
201 PropertyInfo[] properties = new PropertyInfo[end - property];
202 if (module.PropertyPtr.RowCount == 0)
204 for (int j = 0; property < end; property++, j++)
206 properties[j] = new PropertyInfoImpl(module, this, property);
211 for (int j = 0; property < end; property++, j++)
213 properties[j] = new PropertyInfoImpl(module, this, module.PropertyPtr.records[property] - 1);
218 return Empty<PropertyInfo>.Array;
221 public override string __Name
223 get { return typeName; }
226 public override string __Namespace
228 get { return typeNamespace; }
231 public override string Name
233 get { return TypeNameParser.Escape(typeName); }
236 public override string FullName
238 get { return GetFullName(); }
241 public override int MetadataToken
243 get { return (TypeDefTable.Index << 24) + index + 1; }
246 public override Type[] GetGenericArguments()
248 PopulateGenericArguments();
249 return Util.Copy(typeArgs);
252 private void PopulateGenericArguments()
254 if (typeArgs == null)
256 int token = this.MetadataToken;
257 int first = module.GenericParam.FindFirstByOwner(token);
260 typeArgs = Type.EmptyTypes;
264 List<Type> list = new List<Type>();
265 int len = module.GenericParam.records.Length;
266 for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
268 list.Add(new GenericTypeParameter(module, i));
270 typeArgs = list.ToArray();
275 internal override Type GetGenericTypeArgument(int index)
277 PopulateGenericArguments();
278 return typeArgs[index];
281 public override CustomModifiers[] __GetGenericArgumentsCustomModifiers()
283 PopulateGenericArguments();
284 return new CustomModifiers[typeArgs.Length];
287 public override bool IsGenericType
289 get { return IsGenericTypeDefinition; }
292 public override bool IsGenericTypeDefinition
296 if ((typeFlags & (TypeFlags.IsGenericTypeDefinition | TypeFlags.NotGenericTypeDefinition)) == 0)
298 typeFlags |= module.GenericParam.FindFirstByOwner(this.MetadataToken) == -1
299 ? TypeFlags.NotGenericTypeDefinition
300 : TypeFlags.IsGenericTypeDefinition;
302 return (typeFlags & TypeFlags.IsGenericTypeDefinition) != 0;
306 public override Type GetGenericTypeDefinition()
308 if (IsGenericTypeDefinition)
312 throw new InvalidOperationException();
315 public override string ToString()
317 StringBuilder sb = new StringBuilder(this.FullName);
319 foreach (Type arg in GetGenericArguments())
329 return sb.ToString();
332 internal bool IsNestedByFlags
334 get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
337 public override Type DeclaringType
341 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
342 if (!IsNestedByFlags)
346 foreach (int i in module.NestedClass.Filter(this.MetadataToken))
348 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
350 throw new InvalidOperationException();
354 public override StructLayoutAttribute StructLayoutAttribute
358 StructLayoutAttribute layout;
359 switch (this.Attributes & TypeAttributes.LayoutMask)
361 case TypeAttributes.AutoLayout:
362 layout = new StructLayoutAttribute(LayoutKind.Auto);
364 case TypeAttributes.SequentialLayout:
365 layout = new StructLayoutAttribute(LayoutKind.Sequential);
367 case TypeAttributes.ExplicitLayout:
368 layout = new StructLayoutAttribute(LayoutKind.Explicit);
371 throw new BadImageFormatException();
373 switch (this.Attributes & TypeAttributes.StringFormatMask)
375 case TypeAttributes.AnsiClass:
376 layout.CharSet = CharSet.Ansi;
378 case TypeAttributes.UnicodeClass:
379 layout.CharSet = CharSet.Unicode;
381 case TypeAttributes.AutoClass:
382 layout.CharSet = CharSet.Auto;
385 layout.CharSet = CharSet.None;
388 if (!__GetLayout(out layout.Pack, out layout.Size))
390 // compatibility with System.Reflection
397 public override bool __GetLayout(out int packingSize, out int typeSize)
399 foreach (int i in module.ClassLayout.Filter(this.MetadataToken))
401 packingSize = module.ClassLayout.records[i].PackingSize;
402 typeSize = module.ClassLayout.records[i].ClassSize;
410 public override Module Module
412 get { return module; }
415 internal override bool IsModulePseudoType
417 get { return index == 0; }
420 internal override bool IsBaked