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 = new List<Type>();
103 // TODO use binary search?
104 for (int i = 0; i < module.InterfaceImpl.records.Length; i++)
106 if (module.InterfaceImpl.records[i].Class == token)
108 list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
111 return list.ToArray();
114 public override MethodBase[] __GetDeclaredMethods()
116 int method = module.TypeDef.records[index].MethodList - 1;
117 int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
118 MethodBase[] methods = new MethodBase[end - method];
119 for (int i = 0; method < end; method++, i++)
121 methods[i] = module.GetMethodAt(this, method);
126 public override __MethodImplMap __GetMethodImplMap()
128 List<MethodInfo> bodies = new List<MethodInfo>();
129 List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
130 int token = this.MetadataToken;
131 // TODO use binary search?
132 for (int i = 0; i < module.MethodImpl.records.Length; i++)
134 if (module.MethodImpl.records[i].Class == token)
136 MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
137 int index = bodies.IndexOf(body);
140 index = bodies.Count;
142 declarations.Add(new List<MethodInfo>());
144 MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
145 declarations[index].Add(declaration);
148 __MethodImplMap map = new __MethodImplMap();
149 map.TargetType = this;
150 map.MethodBodies = bodies.ToArray();
151 map.MethodDeclarations = new MethodInfo[declarations.Count][];
152 for (int i = 0; i < map.MethodDeclarations.Length; i++)
154 map.MethodDeclarations[i] = declarations[i].ToArray();
159 public override Type[] __GetDeclaredTypes()
161 int token = this.MetadataToken;
162 List<Type> list = new List<Type>();
163 // TODO use binary search?
164 for (int i = 0; i < module.NestedClass.records.Length; i++)
166 if (module.NestedClass.records[i].EnclosingClass == token)
168 list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
171 return list.ToArray();
174 public override PropertyInfo[] __GetDeclaredProperties()
176 int token = this.MetadataToken;
177 // TODO use binary search?
178 for (int i = 0; i < module.PropertyMap.records.Length; i++)
180 if (module.PropertyMap.records[i].Parent == token)
182 int property = module.PropertyMap.records[i].PropertyList - 1;
183 int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
184 PropertyInfo[] properties = new PropertyInfo[end - property];
185 for (int j = 0; property < end; property++, j++)
187 properties[j] = new PropertyInfoImpl(module, this, property);
192 return Empty<PropertyInfo>.Array;
195 public override string __Name
197 get { return typeName; }
200 public override string __Namespace
202 get { return typeNamespace; }
205 public override string Name
207 get { return TypeNameParser.Escape(typeName); }
210 public override string FullName
212 get { return GetFullName(); }
215 public override Type UnderlyingSystemType
220 public override int MetadataToken
222 get { return (TypeDefTable.Index << 24) + index + 1; }
225 public override Type[] GetGenericArguments()
227 PopulateGenericArguments();
228 return Util.Copy(typeArgs);
231 private void PopulateGenericArguments()
233 if (typeArgs == null)
235 int token = this.MetadataToken;
236 int first = module.GenericParam.FindFirstByOwner(token);
239 typeArgs = Type.EmptyTypes;
243 List<Type> list = new List<Type>();
244 int len = module.GenericParam.records.Length;
245 for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
247 list.Add(new GenericTypeParameter(module, i));
249 typeArgs = list.ToArray();
254 internal override Type GetGenericTypeArgument(int index)
256 PopulateGenericArguments();
257 return typeArgs[index];
260 public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
262 PopulateGenericArguments();
263 return Util.Copy(new Type[typeArgs.Length][]);
266 public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
268 PopulateGenericArguments();
269 return Util.Copy(new Type[typeArgs.Length][]);
272 public override bool IsGenericType
274 get { return IsGenericTypeDefinition; }
277 public override bool IsGenericTypeDefinition
279 get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
282 public override Type GetGenericTypeDefinition()
284 if (IsGenericTypeDefinition)
288 throw new InvalidOperationException();
291 public override string ToString()
293 StringBuilder sb = new StringBuilder(this.FullName);
295 foreach (Type arg in GetGenericArguments())
305 return sb.ToString();
308 internal bool IsNestedByFlags
310 get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
313 public override Type DeclaringType
317 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
318 if (!IsNestedByFlags)
322 // TODO use binary search (if sorted)
323 int token = this.MetadataToken;
324 for (int i = 0; i < module.NestedClass.records.Length; i++)
326 if (module.NestedClass.records[i].NestedClass == token)
328 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
331 throw new InvalidOperationException();
335 public override StructLayoutAttribute StructLayoutAttribute
339 StructLayoutAttribute layout;
340 switch (this.Attributes & TypeAttributes.LayoutMask)
342 case TypeAttributes.AutoLayout:
344 case TypeAttributes.SequentialLayout:
345 layout = new StructLayoutAttribute(LayoutKind.Sequential);
347 case TypeAttributes.ExplicitLayout:
348 layout = new StructLayoutAttribute(LayoutKind.Explicit);
351 throw new BadImageFormatException();
353 int token = this.MetadataToken;
354 // TODO use binary search?
355 for (int i = 0; i < module.ClassLayout.records.Length; i++)
357 if (module.ClassLayout.records[i].Parent == token)
359 layout.Pack = module.ClassLayout.records[i].PackingSize;
360 layout.Size = module.ClassLayout.records[i].ClassSize;
361 switch (this.Attributes & TypeAttributes.StringFormatMask)
363 case TypeAttributes.AnsiClass:
364 layout.CharSet = CharSet.Ansi;
366 case TypeAttributes.UnicodeClass:
367 layout.CharSet = CharSet.Unicode;
369 case TypeAttributes.AutoClass:
370 layout.CharSet = CharSet.Auto;
373 layout.CharSet = CharSet.None;
383 public override Module Module
385 get { return module; }
388 internal override bool IsModulePseudoType
390 get { return index == 0; }