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 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
294 get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
297 public override Type GetGenericTypeDefinition()
299 if (IsGenericTypeDefinition)
303 throw new InvalidOperationException();
306 public override string ToString()
308 StringBuilder sb = new StringBuilder(this.FullName);
310 foreach (Type arg in GetGenericArguments())
320 return sb.ToString();
323 internal bool IsNestedByFlags
325 get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
328 public override Type DeclaringType
332 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
333 if (!IsNestedByFlags)
337 foreach (int i in module.NestedClass.Filter(this.MetadataToken))
339 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
341 throw new InvalidOperationException();
345 public override StructLayoutAttribute StructLayoutAttribute
349 StructLayoutAttribute layout;
350 switch (this.Attributes & TypeAttributes.LayoutMask)
352 case TypeAttributes.AutoLayout:
353 layout = new StructLayoutAttribute(LayoutKind.Auto);
355 case TypeAttributes.SequentialLayout:
356 layout = new StructLayoutAttribute(LayoutKind.Sequential);
358 case TypeAttributes.ExplicitLayout:
359 layout = new StructLayoutAttribute(LayoutKind.Explicit);
362 throw new BadImageFormatException();
364 switch (this.Attributes & TypeAttributes.StringFormatMask)
366 case TypeAttributes.AnsiClass:
367 layout.CharSet = CharSet.Ansi;
369 case TypeAttributes.UnicodeClass:
370 layout.CharSet = CharSet.Unicode;
372 case TypeAttributes.AutoClass:
373 layout.CharSet = CharSet.Auto;
376 layout.CharSet = CharSet.None;
379 if (!__GetLayout(out layout.Pack, out layout.Size))
381 // compatibility with System.Reflection
388 public override bool __GetLayout(out int packingSize, out int typeSize)
390 foreach (int i in module.ClassLayout.Filter(this.MetadataToken))
392 packingSize = module.ClassLayout.records[i].PackingSize;
393 typeSize = module.ClassLayout.records[i].ClassSize;
401 public override Module Module
403 get { return module; }
406 internal override bool IsModulePseudoType
408 get { return index == 0; }
411 internal override bool IsBaked