Implement IsGenericType etc. in TypeMirror/MethodMirror.
[mono.git] / mcs / class / Mono.Debugger.Soft / Mono.Debugger.Soft / TypeMirror.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using C = Mono.Cecil;
5 using Mono.Cecil.Metadata;
6
7 namespace Mono.Debugger.Soft
8 {
9         /*
10          * Represents a type in the remote virtual machine.
11          * It might be better to make this a subclass of Type, but that could be
12          * difficult as some of our methods like GetMethods () return Mirror objects.
13          */
14         public class TypeMirror : Mirror
15         {
16                 MethodMirror[] methods;
17                 AssemblyMirror ass;
18                 ModuleMirror module;
19                 C.TypeDefinition meta;
20                 FieldInfoMirror[] fields;
21                 PropertyInfoMirror[] properties;
22                 TypeInfo info;
23                 TypeMirror base_type, element_type, gtd;
24                 TypeMirror[] nested;
25                 CustomAttributeDataMirror[] cattrs;
26                 TypeMirror[] ifaces;
27                 Dictionary<TypeMirror, InterfaceMappingMirror> iface_map;
28
29                 internal const BindingFlags DefaultBindingFlags =
30                 BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
31
32                 internal TypeMirror (VirtualMachine vm, long id) : base (vm, id) {
33                 }
34
35                 public string Name {
36                         get {
37                                 return GetInfo ().name;
38                         }
39             }
40
41                 public string Namespace {
42                         get {
43                                 return GetInfo ().ns;
44                         }
45             }
46
47                 public AssemblyMirror Assembly {
48                         get {
49                                 if (ass == null) {
50                                         ass = vm.GetAssembly (GetInfo ().assembly);
51                                 }
52                                 return ass;
53                         }
54                 }
55
56                 public ModuleMirror Module {
57                         get {
58                                 if (module == null) {
59                                         module = vm.GetModule (GetInfo ().module);
60                                 }                                                                                  
61                                 return module;
62                         }
63                 }
64
65                 public int MetadataToken {
66                         get {
67                                 return GetInfo ().token;
68                         }
69                 }
70
71                 public TypeAttributes Attributes {
72                         get {
73                                 return (TypeAttributes)GetInfo ().attributes;
74                         }
75                 }
76
77                 public TypeMirror BaseType {
78                         get {
79                                 // FIXME: base_type could be null for object/interfaces
80                                 if (base_type == null) {
81                                         base_type = vm.GetType (GetInfo ().base_type);
82                                 }
83                                 return base_type;
84                         }
85                 }
86
87                 public int GetArrayRank () {
88                         GetInfo ();
89                         if (info.rank == 0)
90                                 throw new ArgumentException ("Type must be an array type.");
91                         return info.rank;
92                 }
93
94
95                 public bool IsAbstract {
96                         get {
97                                 return (Attributes & TypeAttributes.Abstract) != 0;
98                         }
99                 }
100
101                 public bool IsAnsiClass {
102                         get {
103                                 return (Attributes & TypeAttributes.StringFormatMask)
104                                 == TypeAttributes.AnsiClass;
105                         }
106                 }
107
108                 public bool IsArray {
109                         get {
110                                 return IsArrayImpl ();
111                         }
112                 }
113
114                 public bool IsAutoClass {
115                         get {
116                                 return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass;
117                         }
118                 }
119
120                 public bool IsAutoLayout {
121                         get {
122                                 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout;
123                         }
124                 }
125
126                 public bool IsByRef {
127                         get {
128                                 return IsByRefImpl ();
129                         }
130                 }
131
132                 public bool IsClass {
133                         get {
134                                 if (IsInterface)
135                                         return false;
136
137                                 return !IsValueType;
138                         }
139                 }
140
141                 public bool IsCOMObject {
142                         get {
143                                 return IsCOMObjectImpl ();
144                         }
145                 }
146
147                 public bool IsContextful {
148                         get {
149                                 return IsContextfulImpl ();
150                         }
151                 }
152
153                 public bool IsEnum {
154                         get {
155                                 return GetInfo ().is_enum;
156                         }
157                 }
158
159                 public bool IsExplicitLayout {
160                         get {
161                                 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout;
162                         }
163                 }
164
165                 public bool IsImport {
166                         get {
167                                 return (Attributes & TypeAttributes.Import) != 0;
168                         }
169                 }
170
171                 public bool IsInterface {
172                         get {
173                                 return (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
174                         }
175                 }
176
177                 public bool IsLayoutSequential {
178                         get {
179                                 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout;
180                         }
181                 }
182
183                 public bool IsMarshalByRef {
184                         get {
185                                 return IsMarshalByRefImpl ();
186                         }
187                 }
188
189                 public bool IsNestedAssembly {
190                         get {
191                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly;
192                         }
193                 }
194
195                 public bool IsNestedFamANDAssem {
196                         get {
197                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem;
198                         }
199                 }
200
201                 public bool IsNestedFamily {
202                         get {
203                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily;
204                         }
205                 }
206
207                 public bool IsNestedFamORAssem {
208                         get {
209                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem;
210                         }
211                 }
212
213                 public bool IsNestedPrivate {
214                         get {
215                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate;
216                         }
217                 }
218
219                 public bool IsNestedPublic {
220                         get {
221                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic;
222                         }
223                 }
224
225                 public bool IsNotPublic {
226                         get {
227                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic;
228                         }
229                 }
230
231                 public bool IsPointer {
232                         get {
233                                 return IsPointerImpl ();
234                         }
235                 }
236
237                 public bool IsPrimitive {
238                         get {
239                                 return IsPrimitiveImpl ();
240                         }
241                 }
242
243                 public bool IsPublic {
244                         get {
245                                 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public;
246                         }
247                 }
248
249                 public bool IsSealed {
250                         get {
251                                 return (Attributes & TypeAttributes.Sealed) != 0;
252                         }
253                 }
254
255                 public bool IsSerializable {
256                         get {
257                                 if ((Attributes & TypeAttributes.Serializable) != 0)
258                                         return true;
259
260                                 // FIXME:
261                                 return false;
262                         }
263                 }
264
265                 public bool IsSpecialName {
266                         get {
267                                 return (Attributes & TypeAttributes.SpecialName) != 0;
268                         }
269                 }
270
271                 public bool IsUnicodeClass {
272                         get {
273                                 return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass;
274                         }
275                 }
276
277                 public bool IsValueType {
278                         get {
279                                 return IsValueTypeImpl ();
280                         }
281                 }
282
283                 public bool HasElementType {
284                         get {
285                                 return HasElementTypeImpl ();
286                         }
287                 }
288
289                 // Since protocol version 2.12
290                 public bool IsGenericTypeDefinition {
291                         get {
292                                 vm.CheckProtocolVersion (2, 12);
293                                 GetInfo ();
294                                 return info.is_gtd;
295                         }
296                 }
297
298                 // Since protocol version 2.12
299                 public bool IsGenericType {
300                         get {
301                                 vm.CheckProtocolVersion (2, 12);
302                                 GetInfo ();
303                                 return info.is_generic_type;
304                         }
305                 }
306
307                 public TypeMirror GetElementType () {
308                         GetInfo ();
309                         if (element_type == null && info.element_type != 0)
310                                 element_type = vm.GetType (info.element_type);
311                         return element_type;
312                 }
313
314                 public TypeMirror GetGenericTypeDefinition () {
315                         vm.CheckProtocolVersion (2, 12);
316                         GetInfo ();
317                         if (gtd == null) {
318                                 if (info.gtd == 0)
319                                         throw new InvalidOperationException ();
320                                 gtd = vm.GetType (info.gtd);
321                         }
322                         return gtd;
323                 }
324
325                 public string FullName {
326                         get {
327                                 return GetInfo ().full_name;
328                         }
329                 }
330
331                 public string CSharpName {
332                         get {
333                                 if (IsArray) {
334                                         if (GetArrayRank () == 1)
335                                                 return GetElementType ().CSharpName + "[]";
336                                         else {
337                                                 string ranks = "";
338                                                 for (int i = 0; i < GetArrayRank (); ++i)
339                                                         ranks += ',';
340                                                 return GetElementType ().CSharpName + "[" + ranks + "]";
341                                         }
342                                 }
343                                 if (IsPrimitive) {
344                                         switch (Name) {
345                                         case "Byte":
346                                                 return "byte";
347                                         case "Int32":
348                                                 return "int";
349                                         case "Boolean":
350                                                 return "bool";
351                                         default:
352                                                 return FullName;
353                                         }
354                                 }
355                                 // FIXME: Only do this for real corlib types
356                                 if (Namespace == "System") {
357                                         string s = Name;
358                                         switch (s) {
359                                         case "String":
360                                                 return "string";
361                                         default:
362                                                 return FullName;
363                                         }
364                                 } else {
365                                         return FullName;
366                                 }
367                         }
368                 }
369
370                 public MethodMirror[] GetMethods () {
371                         if (methods == null) {
372                                 long[] ids = vm.conn.Type_GetMethods (id);
373                                 MethodMirror[] m = new MethodMirror [ids.Length];
374                                 for (int i = 0; i < ids.Length; ++i) {
375                                         m [i] = vm.GetMethod (ids [i]);
376                                 }
377                                 methods = m;
378                         }
379                         return methods;
380                 }
381
382                 // FIXME: Sync this with Type
383                 public MethodMirror GetMethod (string name) {
384                         foreach (var m in GetMethods ())
385                                 if (m.Name == name)
386                                         return m;
387                         return null;
388                 }
389
390                 public FieldInfoMirror[] GetFields () {
391                         if (fields != null)
392                                 return fields;
393
394                         string[] names;
395                         long[] types;
396                         int[] attrs;
397                         long[] ids = vm.conn.Type_GetFields (id, out names, out types, out attrs);
398
399                         FieldInfoMirror[] res = new FieldInfoMirror [ids.Length];
400                         for (int i = 0; i < res.Length; ++i)
401                                 res [i] = new FieldInfoMirror (this, ids [i], names [i], vm.GetType (types [i]), (FieldAttributes)attrs [i]);
402
403                         fields = res;
404                         return fields;
405                 }
406
407                 public FieldInfoMirror GetField (string name) {
408                         if (name == null)
409                                 throw new ArgumentNullException ("name");
410                         foreach (var f in GetFields ())
411                                 if (f.Name == name)
412                                         return f;
413                         return null;
414                 }
415
416                 public TypeMirror[] GetNestedTypes ()
417                 {
418                         return GetNestedTypes (DefaultBindingFlags);
419                 }
420
421                 public TypeMirror[] GetNestedTypes (BindingFlags bindingAttr) {
422                         if (nested != null)
423                                 return nested;
424
425                         // FIXME: bindingAttr
426                         GetInfo ();
427                         var arr = new TypeMirror [info.nested.Length];
428                         for (int i = 0; i < arr.Length; ++i)
429                                 arr [i] = vm.GetType (info.nested [i]);
430                         nested = arr;
431
432                         return nested;
433                 }
434
435                 public PropertyInfoMirror[] GetProperties () {
436                         return GetProperties (DefaultBindingFlags);
437                 }
438
439                 public PropertyInfoMirror[] GetProperties (BindingFlags bindingAttr) {
440                         if (properties != null)
441                                 return properties;
442
443                         PropInfo[] info = vm.conn.Type_GetProperties (id);
444
445                         PropertyInfoMirror[] res = new PropertyInfoMirror [info.Length];
446                         for (int i = 0; i < res.Length; ++i)
447                                 res [i] = new PropertyInfoMirror (this, info [i].id, info [i].name, vm.GetMethod (info [i].get_method), vm.GetMethod (info [i].set_method), (PropertyAttributes)info [i].attrs);
448
449                         properties = res;
450                         return properties;
451                 }
452
453                 public PropertyInfoMirror GetProperty (string name) {
454                         if (name == null)
455                                 throw new ArgumentNullException ("name");
456                         foreach (var p in GetProperties ())
457                                 if (p.Name == name)
458                                         return p;
459                         return null;
460                 }
461
462                 public virtual bool IsAssignableFrom (TypeMirror c) {
463                         if (c == null)
464                                 throw new ArgumentNullException ("c");
465
466                         CheckMirror (c);
467
468                         // This is complex so do it in the debuggee
469                         return vm.conn.Type_IsAssignableFrom (id, c.Id);
470                 }
471
472                 public Value GetValue (FieldInfoMirror field) {
473                         return GetValues (new FieldInfoMirror [] { field }) [0];
474                 }
475
476                 public Value[] GetValues (IList<FieldInfoMirror> fields, ThreadMirror thread) {
477                         if (fields == null)
478                                 throw new ArgumentNullException ("fields");
479                         foreach (FieldInfoMirror f in fields) {
480                                 if (f == null)
481                                         throw new ArgumentNullException ("field");
482                                 CheckMirror (f);
483                         }
484                         long[] ids = new long [fields.Count];
485                         for (int i = 0; i < fields.Count; ++i)
486                                 ids [i] = fields [i].Id;
487                         try {
488                                 return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread !=  null ? thread.Id : 0));
489                         } catch (CommandException ex) {
490                                 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
491                                         throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
492                                 else
493                                         throw;
494                         }
495                 }
496
497                 public Value[] GetValues (IList<FieldInfoMirror> fields) {
498                         return GetValues (fields, null);
499                 }
500
501                 /*
502                  * Return the value of the [ThreadStatic] field FIELD on the thread THREAD.
503                  */
504                 public Value GetValue (FieldInfoMirror field, ThreadMirror thread) {
505                         if (thread == null)
506                                 throw new ArgumentNullException ("thread");
507                         CheckMirror (thread);
508                         return GetValues (new FieldInfoMirror [] { field }, thread) [0];
509                 }
510
511                 public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
512                         if (fields == null)
513                                 throw new ArgumentNullException ("fields");
514                         if (values == null)
515                                 throw new ArgumentNullException ("values");
516                         foreach (FieldInfoMirror f in fields) {
517                                 if (f == null)
518                                         throw new ArgumentNullException ("field");
519                                 CheckMirror (f);
520                         }
521                         foreach (Value v in values) {
522                                 if (v == null)
523                                         throw new ArgumentNullException ("values");
524                                 CheckMirror (v);
525                         }
526                         long[] ids = new long [fields.Count];
527                         for (int i = 0; i < fields.Count; ++i)
528                                 ids [i] = fields [i].Id;
529                         try {
530                                 vm.conn.Type_SetValues (id, ids, vm.EncodeValues (values));
531                         } catch (CommandException ex) {
532                                 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
533                                         throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
534                                 else
535                                         throw;
536                         }
537                 }
538
539                 public void SetValue (FieldInfoMirror field, Value value) {
540                         SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
541                 }
542
543                 public ObjectMirror GetTypeObject () {
544                         return vm.GetObject (vm.conn.Type_GetObject (id));
545                 }
546
547                 /*
548                  * Return a list of source files without path info, where methods of 
549                  * this type are defined. Return an empty list if the information is not 
550                  * available. 
551                  * This can be used by a debugger to find out which types occur in a 
552                  * given source file, to filter the list of methods whose locations
553                  * have to be checked when placing breakpoints.
554                  */
555                 public string[] GetSourceFiles () {
556                         return GetSourceFiles (false);
557                 }
558
559                 string[] source_files;
560                 string[] source_files_full_path;
561                 public string[] GetSourceFiles (bool return_full_paths) {
562                         string[] res = return_full_paths ? source_files_full_path : source_files;
563                         if (res == null) {
564                                 res = vm.conn.Type_GetSourceFiles (id, return_full_paths);
565                                 if (return_full_paths)
566                                         source_files_full_path = res;
567                                 else
568                                         source_files = res;
569                         }
570                         return res;
571                 }
572
573                 public C.TypeDefinition Metadata {
574                         get {
575                                 if (meta == null) {
576                                         if (Assembly.Metadata == null || MetadataToken == 0)
577                                                 return null;
578                                         meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupToken (MetadataToken);
579                                 }
580                                 return meta;
581                         }
582                 }
583
584                 TypeInfo GetInfo () {
585                         if (info == null)
586                                 info = vm.conn.Type_GetInfo (id);
587                         return info;
588                 }
589
590                 protected virtual TypeAttributes GetAttributeFlagsImpl () {
591                         return (TypeAttributes)GetInfo ().attributes;
592                 }
593
594                 protected virtual bool HasElementTypeImpl () {
595                         return IsArray || IsByRef || IsPointer;
596                 }
597
598                 protected virtual bool IsArrayImpl () {
599                         return GetInfo ().rank > 0;
600                 }
601
602                 protected virtual bool IsByRefImpl () {
603                         return GetInfo ().is_byref;
604                 }
605
606                 protected virtual bool IsCOMObjectImpl () {
607                         return false;
608                 }
609
610                 protected virtual bool IsPointerImpl () {
611                         return GetInfo ().is_pointer;
612                 }
613
614                 protected virtual bool IsPrimitiveImpl () {
615                         return GetInfo ().is_primitive;
616                 }
617
618                 protected virtual bool IsValueTypeImpl ()
619                 {
620                         return GetInfo ().is_valuetype;
621                 }
622                 
623                 protected virtual bool IsContextfulImpl ()
624                 {
625                         // FIXME:
626                         return false;
627                 }
628
629                 protected virtual bool IsMarshalByRefImpl ()
630                 {
631                         // FIXME:
632                         return false;
633                 }
634
635                 // Same as Enum.GetUnderlyingType ()
636                 public TypeMirror EnumUnderlyingType {
637                         get {
638                                 if (!IsEnum)
639                                         throw new ArgumentException ("Type is not an enum type.");
640                                 foreach (FieldInfoMirror f in GetFields ()) {
641                                         if (!f.IsStatic)
642                                                 return f.FieldType;
643                                 }
644                                 throw new NotImplementedException ();
645                         }
646                 }
647
648                 /*
649                  * Creating the custom attributes themselves could modify the behavior of the
650                  * debuggee, so we return objects similar to the CustomAttributeData objects
651                  * used by the reflection-only functionality on .net.
652                  */
653                 public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
654                         return GetCAttrs (null, inherit);
655                 }
656
657                 public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
658                         if (attributeType == null)
659                                 throw new ArgumentNullException ("attributeType");
660                         return GetCAttrs (attributeType, inherit);
661                 }
662
663                 CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
664                         if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
665                                 cattrs = new CustomAttributeDataMirror [0];
666
667                         // FIXME: Handle inherit
668                         if (cattrs == null) {
669                                 CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
670                                 cattrs = CustomAttributeDataMirror.Create (vm, info);
671                         }
672                         var res = new List<CustomAttributeDataMirror> ();
673                         foreach (var attr in cattrs)
674                                 if (type == null || attr.Constructor.DeclaringType == type)
675                                         res.Add (attr);
676                         return res.ToArray ();
677                 }
678
679                 public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
680                         if (vm.conn.Version.AtLeast (2, 6)) {
681                                 long[] ids = vm.conn.Type_GetMethodsByNameFlags (id, name, (int)flags, ignoreCase);
682                                 MethodMirror[] m = new MethodMirror [ids.Length];
683                                 for (int i = 0; i < ids.Length; ++i)
684                                         m [i] = vm.GetMethod (ids [i]);
685                                 return m;
686                         } else {
687                                 if (flags != (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.NonPublic))
688                                         throw new NotImplementedException ();
689                                 var res = new List<MethodMirror> ();
690                                 foreach (MethodMirror m in GetMethods ()) {
691                                         if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase)))
692                                                 res.Add (m);
693                                 }
694                                 return res.ToArray ();
695                         }
696                 }
697
698                 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
699                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
700                 }
701
702                 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
703                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
704                 }
705
706                 [Obsolete ("Use the overload without the 'vm' argument")]
707                 public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
708                         return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
709                 }
710
711                 public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
712                         return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
713                 }
714
715                 public Value EndInvokeMethod (IAsyncResult asyncResult) {
716                         return ObjectMirror.EndInvokeMethodInternal (asyncResult);
717                 }
718
719                 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
720                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
721                 }                       
722
723                 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
724                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
725                 }
726
727                 // Since protocol version 2.11
728                 public TypeMirror[] GetInterfaces () {
729                         if (ifaces == null)
730                                 ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id));
731                         return ifaces;
732                 }
733
734                 // Since protocol version 2.11
735                 public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) {
736                         if (interfaceType == null)
737                                 throw new ArgumentNullException ("interfaceType");
738                         if (!interfaceType.IsInterface)
739                                 throw new ArgumentException ("Argument must be an interface.", "interfaceType");
740                         if (IsInterface)
741                                 throw new ArgumentException ("'this' type cannot be an interface itself");
742
743                         if (iface_map == null) {
744                                 // Query the info in bulk
745                                 GetInterfaces ();
746                                 var ids = new long [ifaces.Length];
747                                 for (int i = 0; i < ifaces.Length; ++i)
748                                         ids [i] = ifaces [i].Id;
749
750                                 var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids);
751
752                                 var imap = new Dictionary<TypeMirror, InterfaceMappingMirror> ();
753                                 for (int i = 0; i < ifacemap.Length; ++i) {
754                                         IfaceMapInfo info = ifacemap [i];
755
756                                         MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length];
757                                         for (int j = 0; j < info.iface_methods.Length; ++j)
758                                                 imethods [j] = vm.GetMethod (info.iface_methods [j]);
759
760                                         MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length];
761                                         for (int j = 0; j < info.target_methods.Length; ++j)
762                                                 tmethods [j] = vm.GetMethod (info.target_methods [j]);
763
764                                         InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods);
765
766                                         imap [map.InterfaceType] = map;
767                                 }
768
769                                 iface_map = imap;
770                         }
771
772                         InterfaceMappingMirror res;
773                         if (!iface_map.TryGetValue (interfaceType, out res))
774                                 throw new ArgumentException ("Interface not found", "interfaceType");
775                         return res;
776                 }
777
778     }
779 }