2 Copyright (C) 2009 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 = TypeNameParser.Escape(module.GetString(module.TypeDef.records[index].TypeName));
45 this.typeNamespace = TypeNameParser.Escape(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 Type UnderlyingSystemType
210 public override int MetadataToken
212 get { return (TypeDefTable.Index << 24) + index + 1; }
215 public override Type[] GetGenericArguments()
217 PopulateGenericArguments();
218 return Util.Copy(typeArgs);
221 private void PopulateGenericArguments()
223 if (typeArgs == null)
225 int token = this.MetadataToken;
226 int first = module.GenericParam.FindFirstByOwner(token);
229 typeArgs = Type.EmptyTypes;
233 List<Type> list = new List<Type>();
234 int len = module.GenericParam.records.Length;
235 for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
237 list.Add(new GenericTypeParameter(module, i));
239 typeArgs = list.ToArray();
244 internal override Type GetGenericTypeArgument(int index)
246 PopulateGenericArguments();
247 return typeArgs[index];
250 public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
252 PopulateGenericArguments();
253 return Util.Copy(new Type[typeArgs.Length][]);
256 public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
258 PopulateGenericArguments();
259 return Util.Copy(new Type[typeArgs.Length][]);
262 public override bool IsGenericType
264 get { return IsGenericTypeDefinition; }
267 public override bool IsGenericTypeDefinition
269 get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
272 public override Type GetGenericTypeDefinition()
274 if (IsGenericTypeDefinition)
278 throw new InvalidOperationException();
281 public override string ToString()
283 StringBuilder sb = new StringBuilder(this.FullName);
285 foreach (Type arg in GetGenericArguments())
295 return sb.ToString();
298 public override Type DeclaringType
302 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
303 if ((this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) == 0)
307 // TODO use binary search (if sorted)
308 int token = this.MetadataToken;
309 for (int i = 0; i < module.NestedClass.records.Length; i++)
311 if (module.NestedClass.records[i].NestedClass == token)
313 return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
316 throw new InvalidOperationException();
320 public override StructLayoutAttribute StructLayoutAttribute
324 StructLayoutAttribute layout;
325 switch (this.Attributes & TypeAttributes.LayoutMask)
327 case TypeAttributes.AutoLayout:
329 case TypeAttributes.SequentialLayout:
330 layout = new StructLayoutAttribute(LayoutKind.Sequential);
332 case TypeAttributes.ExplicitLayout:
333 layout = new StructLayoutAttribute(LayoutKind.Explicit);
336 throw new BadImageFormatException();
338 int token = this.MetadataToken;
339 // TODO use binary search?
340 for (int i = 0; i < module.ClassLayout.records.Length; i++)
342 if (module.ClassLayout.records[i].Parent == token)
344 layout.Pack = module.ClassLayout.records[i].PackingSize;
345 layout.Size = module.ClassLayout.records[i].ClassSize;
346 switch (this.Attributes & TypeAttributes.StringFormatMask)
348 case TypeAttributes.AnsiClass:
349 layout.CharSet = CharSet.Ansi;
351 case TypeAttributes.UnicodeClass:
352 layout.CharSet = CharSet.Unicode;
354 case TypeAttributes.AutoClass:
355 layout.CharSet = CharSet.Auto;
358 layout.CharSet = CharSet.None;
368 public override Module Module
370 get { return module; }
373 internal override bool IsModulePseudoType
375 get { return index == 0; }