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 : Type
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 int token = this.MetadataToken;
70 // TODO use binary search?
71 for (int i = 0; i < module.EventMap.records.Length; i++)
73 if (module.EventMap.records[i].Parent == token)
75 int evt = module.EventMap.records[i].EventList - 1;
76 int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length;
77 EventInfo[] events = new EventInfo[end - evt];
78 if (module.EventPtr.RowCount == 0)
80 for (int j = 0; evt < end; evt++, j++)
82 events[j] = new EventInfoImpl(module, this, evt);
87 for (int j = 0; evt < end; evt++, j++)
89 events[j] = new EventInfoImpl(module, this, module.EventPtr.records[evt] - 1);
95 return Empty<EventInfo>.Array;
98 public override FieldInfo[] __GetDeclaredFields()
100 int field = module.TypeDef.records[index].FieldList - 1;
101 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length;
102 FieldInfo[] fields = new FieldInfo[end - field];
103 if (module.FieldPtr.RowCount == 0)
105 for (int i = 0; field < end; i++, field++)
107 fields[i] = module.GetFieldAt(this, field);
112 for (int i = 0; field < end; i++, field++)
114 fields[i] = module.GetFieldAt(this, module.FieldPtr.records[field] - 1);
120 public override Type[] __GetDeclaredInterfaces()
122 int token = this.MetadataToken;
123 List<Type> list = null;
124 // TODO use binary search?
125 for (int i = 0; i < module.InterfaceImpl.records.Length; i++)
127 if (module.InterfaceImpl.records[i].Class == token)
131 list = new List<Type>();
133 list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
136 return Util.ToArray(list, Type.EmptyTypes);
139 public override MethodBase[] __GetDeclaredMethods()
141 int method = module.TypeDef.records[index].MethodList - 1;
142 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
143 MethodBase[] methods = new MethodBase[end - method];
144 if (module.MethodPtr.RowCount == 0)
146 for (int i = 0; method < end; method++, i++)
148 methods[i] = module.GetMethodAt(this, method);
153 for (int i = 0; method < end; method++, i++)
155 methods[i] = module.GetMethodAt(this, module.MethodPtr.records[method] - 1);
161 public override __MethodImplMap __GetMethodImplMap()
163 List<MethodInfo> bodies = new List<MethodInfo>();
164 List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
165 int token = this.MetadataToken;
166 // TODO use binary search?
167 for (int i = 0; i < module.MethodImpl.records.Length; i++)
169 if (module.MethodImpl.records[i].Class == token)
171 MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
172 int index = bodies.IndexOf(body);
175 index = bodies.Count;
177 declarations.Add(new List<MethodInfo>());
179 MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
180 declarations[index].Add(declaration);
183 __MethodImplMap map = new __MethodImplMap();
184 map.TargetType = this;
185 map.MethodBodies = bodies.ToArray();
186 map.MethodDeclarations = new MethodInfo[declarations.Count][];
187 for (int i = 0; i < map.MethodDeclarations.Length; i++)
189 map.MethodDeclarations[i] = declarations[i].ToArray();
194 public override Type[] __GetDeclaredTypes()
196 int token = this.MetadataToken;
197 List<Type> list = new List<Type>();
198 // TODO use binary search?
199 for (int i = 0; i < module.NestedClass.records.Length; i++)
201 if (module.NestedClass.records[i].EnclosingClass == token)
203 list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
206 return list.ToArray();
209 public override PropertyInfo[] __GetDeclaredProperties()
211 int token = this.MetadataToken;
212 // TODO use binary search?
213 for (int i = 0; i < module.PropertyMap.records.Length; i++)
215 if (module.PropertyMap.records[i].Parent == token)
217 int property = module.PropertyMap.records[i].PropertyList - 1;
218 int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
219 PropertyInfo[] properties = new PropertyInfo[end - property];
220 if (module.PropertyPtr.RowCount == 0)
222 for (int j = 0; property < end; property++, j++)
224 properties[j] = new PropertyInfoImpl(module, this, property);
229 for (int j = 0; property < end; property++, j++)
231 properties[j] = new PropertyInfoImpl(module, this, module.PropertyPtr.records[property] - 1);
237 return Empty<PropertyInfo>.Array;
240 public override string __Name
242 get { return typeName; }
245 public override string __Namespace
247 get { return typeNamespace; }
250 public override string Name
252 get { return TypeNameParser.Escape(typeName); }
255 public override string FullName
257 get { return GetFullName(); }
260 public override int MetadataToken
262 get { return (TypeDefTable.Index << 24) + index + 1; }
265 public override Type[] GetGenericArguments()
267 PopulateGenericArguments();
268 return Util.Copy(typeArgs);
271 private void PopulateGenericArguments()
273 if (typeArgs == null)
275 int token = this.MetadataToken;
276 int first = module.GenericParam.FindFirstByOwner(token);
279 typeArgs = Type.EmptyTypes;
283 List<Type> list = new List<Type>();
284 int len = module.GenericParam.records.Length;
285 for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
287 list.Add(new GenericTypeParameter(module, i));
289 typeArgs = list.ToArray();
294 internal override Type GetGenericTypeArgument(int index)
296 PopulateGenericArguments();
297 return typeArgs[index];
300 public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
302 PopulateGenericArguments();
303 return Util.Copy(new Type[typeArgs.Length][]);
306 public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
308 PopulateGenericArguments();
309 return Util.Copy(new Type[typeArgs.Length][]);
312 public override bool IsGenericType
314 get { return IsGenericTypeDefinition; }
317 public override bool IsGenericTypeDefinition
319 get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
322 public override Type GetGenericTypeDefinition()
324 if (IsGenericTypeDefinition)
328 throw new InvalidOperationException();
331 public override string ToString()
333 StringBuilder sb = new StringBuilder(this.FullName);
335 foreach (Type arg in GetGenericArguments())
345 return sb.ToString();
348 internal bool IsNestedByFlags
350 get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
353 public override Type DeclaringType
357 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
358 if (!IsNestedByFlags)
362 // TODO use binary search (if sorted)
363 int token = this.MetadataToken;
364 for (int i = 0; i < module.NestedClass.records.Length; i++)
366 if (module.NestedClass.records[i].NestedClass == token)
368 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
371 throw new InvalidOperationException();
375 public override StructLayoutAttribute StructLayoutAttribute
379 StructLayoutAttribute layout;
380 switch (this.Attributes & TypeAttributes.LayoutMask)
382 case TypeAttributes.AutoLayout:
383 layout = new StructLayoutAttribute(LayoutKind.Auto);
385 case TypeAttributes.SequentialLayout:
386 layout = new StructLayoutAttribute(LayoutKind.Sequential);
388 case TypeAttributes.ExplicitLayout:
389 layout = new StructLayoutAttribute(LayoutKind.Explicit);
392 throw new BadImageFormatException();
394 switch (this.Attributes & TypeAttributes.StringFormatMask)
396 case TypeAttributes.AnsiClass:
397 layout.CharSet = CharSet.Ansi;
399 case TypeAttributes.UnicodeClass:
400 layout.CharSet = CharSet.Unicode;
402 case TypeAttributes.AutoClass:
403 layout.CharSet = CharSet.Auto;
406 layout.CharSet = CharSet.None;
409 if (!__GetLayout(out layout.Pack, out layout.Size))
411 // compatibility with System.Reflection
418 public override bool __GetLayout(out int packingSize, out int typeSize)
420 int token = this.MetadataToken;
421 // TODO use binary search?
422 for (int i = 0; i < module.ClassLayout.records.Length; i++)
424 if (module.ClassLayout.records[i].Parent == token)
426 packingSize = module.ClassLayout.records[i].PackingSize;
427 typeSize = module.ClassLayout.records[i].ClassSize;
436 public override Module Module
438 get { return module; }
441 internal override bool IsModulePseudoType
443 get { return index == 0; }