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 CustomModifiers[] __GetGenericArgumentsCustomModifiers()
302 PopulateGenericArguments();
303 return new CustomModifiers[typeArgs.Length];
306 public override bool IsGenericType
308 get { return IsGenericTypeDefinition; }
311 public override bool IsGenericTypeDefinition
313 get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
316 public override Type GetGenericTypeDefinition()
318 if (IsGenericTypeDefinition)
322 throw new InvalidOperationException();
325 public override string ToString()
327 StringBuilder sb = new StringBuilder(this.FullName);
329 foreach (Type arg in GetGenericArguments())
339 return sb.ToString();
342 internal bool IsNestedByFlags
344 get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
347 public override Type DeclaringType
351 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
352 if (!IsNestedByFlags)
356 // TODO use binary search (if sorted)
357 int token = this.MetadataToken;
358 for (int i = 0; i < module.NestedClass.records.Length; i++)
360 if (module.NestedClass.records[i].NestedClass == token)
362 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
365 throw new InvalidOperationException();
369 public override StructLayoutAttribute StructLayoutAttribute
373 StructLayoutAttribute layout;
374 switch (this.Attributes & TypeAttributes.LayoutMask)
376 case TypeAttributes.AutoLayout:
377 layout = new StructLayoutAttribute(LayoutKind.Auto);
379 case TypeAttributes.SequentialLayout:
380 layout = new StructLayoutAttribute(LayoutKind.Sequential);
382 case TypeAttributes.ExplicitLayout:
383 layout = new StructLayoutAttribute(LayoutKind.Explicit);
386 throw new BadImageFormatException();
388 switch (this.Attributes & TypeAttributes.StringFormatMask)
390 case TypeAttributes.AnsiClass:
391 layout.CharSet = CharSet.Ansi;
393 case TypeAttributes.UnicodeClass:
394 layout.CharSet = CharSet.Unicode;
396 case TypeAttributes.AutoClass:
397 layout.CharSet = CharSet.Auto;
400 layout.CharSet = CharSet.None;
403 if (!__GetLayout(out layout.Pack, out layout.Size))
405 // compatibility with System.Reflection
412 public override bool __GetLayout(out int packingSize, out int typeSize)
414 int token = this.MetadataToken;
415 // TODO use binary search?
416 for (int i = 0; i < module.ClassLayout.records.Length; i++)
418 if (module.ClassLayout.records[i].Parent == token)
420 packingSize = module.ClassLayout.records[i].PackingSize;
421 typeSize = module.ClassLayout.records[i].ClassSize;
430 public override Module Module
432 get { return module; }
435 internal override bool IsModulePseudoType
437 get { return index == 0; }
440 internal override IList<CustomAttributeData> GetInterfaceImplCustomAttributes(Type interfaceType, Type attributeType)
442 int token = this.MetadataToken;
443 // TODO use binary search?
444 for (int i = 0; i < module.InterfaceImpl.records.Length; i++)
446 if (module.InterfaceImpl.records[i].Class == token
447 && module.ResolveType(module.InterfaceImpl.records[i].Interface, this) == interfaceType)
449 return module.GetCustomAttributes((InterfaceImplTable.Index << 24) | (i + 1), attributeType);
452 return Empty<CustomAttributeData>.Array;