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);
48 public override Type BaseType
52 int extends = module.TypeDef.records[index].Extends;
53 if ((extends & 0xFFFFFF) == 0)
57 return module.ResolveType(extends, this);
61 public override TypeAttributes Attributes
63 get { return (TypeAttributes)module.TypeDef.records[index].Flags; }
66 public override EventInfo[] __GetDeclaredEvents()
68 int token = this.MetadataToken;
69 // TODO use binary search?
70 for (int i = 0; i < module.EventMap.records.Length; i++)
72 if (module.EventMap.records[i].Parent == token)
74 int evt = module.EventMap.records[i].EventList - 1;
75 int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length;
76 EventInfo[] events = new EventInfo[end - evt];
77 for (int j = 0; evt < end; evt++, j++)
79 events[j] = new EventInfoImpl(module, this, evt);
84 return Empty<EventInfo>.Array;
87 public override FieldInfo[] __GetDeclaredFields()
89 int field = module.TypeDef.records[index].FieldList - 1;
90 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length;
91 FieldInfo[] fields = new FieldInfo[end - field];
92 for (int i = 0; field < end; i++, field++)
94 fields[i] = module.GetFieldAt(this, field);
99 public override Type[] __GetDeclaredInterfaces()
101 int token = this.MetadataToken;
102 List<Type> list = null;
103 // TODO use binary search?
104 for (int i = 0; i < module.InterfaceImpl.records.Length; i++)
106 if (module.InterfaceImpl.records[i].Class == token)
110 list = new List<Type>();
112 list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
115 return Util.ToArray(list, Type.EmptyTypes);
118 public override MethodBase[] __GetDeclaredMethods()
120 int method = module.TypeDef.records[index].MethodList - 1;
121 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
122 MethodBase[] methods = new MethodBase[end - method];
123 for (int i = 0; method < end; method++, i++)
125 methods[i] = module.GetMethodAt(this, method);
130 public override __MethodImplMap __GetMethodImplMap()
132 List<MethodInfo> bodies = new List<MethodInfo>();
133 List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
134 int token = this.MetadataToken;
135 // TODO use binary search?
136 for (int i = 0; i < module.MethodImpl.records.Length; i++)
138 if (module.MethodImpl.records[i].Class == token)
140 MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
141 int index = bodies.IndexOf(body);
144 index = bodies.Count;
146 declarations.Add(new List<MethodInfo>());
148 MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
149 declarations[index].Add(declaration);
152 __MethodImplMap map = new __MethodImplMap();
153 map.TargetType = this;
154 map.MethodBodies = bodies.ToArray();
155 map.MethodDeclarations = new MethodInfo[declarations.Count][];
156 for (int i = 0; i < map.MethodDeclarations.Length; i++)
158 map.MethodDeclarations[i] = declarations[i].ToArray();
163 public override Type[] __GetDeclaredTypes()
165 int token = this.MetadataToken;
166 List<Type> list = new List<Type>();
167 // TODO use binary search?
168 for (int i = 0; i < module.NestedClass.records.Length; i++)
170 if (module.NestedClass.records[i].EnclosingClass == token)
172 list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
175 return list.ToArray();
178 public override PropertyInfo[] __GetDeclaredProperties()
180 int token = this.MetadataToken;
181 // TODO use binary search?
182 for (int i = 0; i < module.PropertyMap.records.Length; i++)
184 if (module.PropertyMap.records[i].Parent == token)
186 int property = module.PropertyMap.records[i].PropertyList - 1;
187 int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
188 PropertyInfo[] properties = new PropertyInfo[end - property];
189 for (int j = 0; property < end; property++, j++)
191 properties[j] = new PropertyInfoImpl(module, this, property);
196 return Empty<PropertyInfo>.Array;
199 public override string __Name
201 get { return typeName; }
204 public override string __Namespace
206 get { return typeNamespace; }
209 public override string Name
211 get { return TypeNameParser.Escape(typeName); }
214 public override string FullName
216 get { return GetFullName(); }
219 public override int MetadataToken
221 get { return (TypeDefTable.Index << 24) + index + 1; }
224 public override Type[] GetGenericArguments()
226 PopulateGenericArguments();
227 return Util.Copy(typeArgs);
230 private void PopulateGenericArguments()
232 if (typeArgs == null)
234 int token = this.MetadataToken;
235 int first = module.GenericParam.FindFirstByOwner(token);
238 typeArgs = Type.EmptyTypes;
242 List<Type> list = new List<Type>();
243 int len = module.GenericParam.records.Length;
244 for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
246 list.Add(new GenericTypeParameter(module, i));
248 typeArgs = list.ToArray();
253 internal override Type GetGenericTypeArgument(int index)
255 PopulateGenericArguments();
256 return typeArgs[index];
259 public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
261 PopulateGenericArguments();
262 return Util.Copy(new Type[typeArgs.Length][]);
265 public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
267 PopulateGenericArguments();
268 return Util.Copy(new Type[typeArgs.Length][]);
271 public override bool IsGenericType
273 get { return IsGenericTypeDefinition; }
276 public override bool IsGenericTypeDefinition
278 get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
281 public override Type GetGenericTypeDefinition()
283 if (IsGenericTypeDefinition)
287 throw new InvalidOperationException();
290 public override string ToString()
292 StringBuilder sb = new StringBuilder(this.FullName);
294 foreach (Type arg in GetGenericArguments())
304 return sb.ToString();
307 internal bool IsNestedByFlags
309 get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
312 public override Type DeclaringType
316 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
317 if (!IsNestedByFlags)
321 // TODO use binary search (if sorted)
322 int token = this.MetadataToken;
323 for (int i = 0; i < module.NestedClass.records.Length; i++)
325 if (module.NestedClass.records[i].NestedClass == token)
327 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
330 throw new InvalidOperationException();
334 public override StructLayoutAttribute StructLayoutAttribute
338 StructLayoutAttribute layout;
339 switch (this.Attributes & TypeAttributes.LayoutMask)
341 case TypeAttributes.AutoLayout:
343 case TypeAttributes.SequentialLayout:
344 layout = new StructLayoutAttribute(LayoutKind.Sequential);
346 case TypeAttributes.ExplicitLayout:
347 layout = new StructLayoutAttribute(LayoutKind.Explicit);
350 throw new BadImageFormatException();
352 int token = this.MetadataToken;
353 // TODO use binary search?
354 for (int i = 0; i < module.ClassLayout.records.Length; i++)
356 if (module.ClassLayout.records[i].Parent == token)
358 layout.Pack = module.ClassLayout.records[i].PackingSize;
359 layout.Size = module.ClassLayout.records[i].ClassSize;
360 switch (this.Attributes & TypeAttributes.StringFormatMask)
362 case TypeAttributes.AnsiClass:
363 layout.CharSet = CharSet.Ansi;
365 case TypeAttributes.UnicodeClass:
366 layout.CharSet = CharSet.Unicode;
368 case TypeAttributes.AutoClass:
369 layout.CharSet = CharSet.Auto;
372 layout.CharSet = CharSet.None;
382 public override Module Module
384 get { return module; }
387 internal override bool IsModulePseudoType
389 get { return index == 0; }