Merge pull request #225 from mistoll/master
[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                 public bool IsGenericType {
299                         get {
300                                 if (vm.Version.AtLeast (2, 12)) {
301                                         return GetInfo ().is_generic_type;
302                                 } else {
303                                         return Name.IndexOf ('`') != -1;
304                                 }
305                         }
306                 }
307
308                 public TypeMirror GetElementType () {
309                         GetInfo ();
310                         if (element_type == null && info.element_type != 0)
311                                 element_type = vm.GetType (info.element_type);
312                         return element_type;
313                 }
314
315                 public TypeMirror GetGenericTypeDefinition () {
316                         vm.CheckProtocolVersion (2, 12);
317                         GetInfo ();
318                         if (gtd == null) {
319                                 if (info.gtd == 0)
320                                         throw new InvalidOperationException ();
321                                 gtd = vm.GetType (info.gtd);
322                         }
323                         return gtd;
324                 }
325
326                 public string FullName {
327                         get {
328                                 return GetInfo ().full_name;
329                         }
330                 }
331
332                 public string CSharpName {
333                         get {
334                                 if (IsArray) {
335                                         if (GetArrayRank () == 1)
336                                                 return GetElementType ().CSharpName + "[]";
337                                         else {
338                                                 string ranks = "";
339                                                 for (int i = 0; i < GetArrayRank (); ++i)
340                                                         ranks += ',';
341                                                 return GetElementType ().CSharpName + "[" + ranks + "]";
342                                         }
343                                 }
344                                 if (IsPrimitive) {
345                                         switch (Name) {
346                                         case "Byte":
347                                                 return "byte";
348                                         case "Int32":
349                                                 return "int";
350                                         case "Boolean":
351                                                 return "bool";
352                                         default:
353                                                 return FullName;
354                                         }
355                                 }
356                                 // FIXME: Only do this for real corlib types
357                                 if (Namespace == "System") {
358                                         string s = Name;
359                                         switch (s) {
360                                         case "String":
361                                                 return "string";
362                                         default:
363                                                 return FullName;
364                                         }
365                                 } else {
366                                         return FullName;
367                                 }
368                         }
369                 }
370
371                 public MethodMirror[] GetMethods () {
372                         if (methods == null) {
373                                 long[] ids = vm.conn.Type_GetMethods (id);
374                                 MethodMirror[] m = new MethodMirror [ids.Length];
375                                 for (int i = 0; i < ids.Length; ++i) {
376                                         m [i] = vm.GetMethod (ids [i]);
377                                 }
378                                 methods = m;
379                         }
380                         return methods;
381                 }
382
383                 // FIXME: Sync this with Type
384                 public MethodMirror GetMethod (string name) {
385                         foreach (var m in GetMethods ())
386                                 if (m.Name == name)
387                                         return m;
388                         return null;
389                 }
390
391                 public FieldInfoMirror[] GetFields () {
392                         if (fields != null)
393                                 return fields;
394
395                         string[] names;
396                         long[] types;
397                         int[] attrs;
398                         long[] ids = vm.conn.Type_GetFields (id, out names, out types, out attrs);
399
400                         FieldInfoMirror[] res = new FieldInfoMirror [ids.Length];
401                         for (int i = 0; i < res.Length; ++i)
402                                 res [i] = new FieldInfoMirror (this, ids [i], names [i], vm.GetType (types [i]), (FieldAttributes)attrs [i]);
403
404                         fields = res;
405                         return fields;
406                 }
407
408                 public FieldInfoMirror GetField (string name) {
409                         if (name == null)
410                                 throw new ArgumentNullException ("name");
411                         foreach (var f in GetFields ())
412                                 if (f.Name == name)
413                                         return f;
414                         return null;
415                 }
416
417                 public TypeMirror[] GetNestedTypes ()
418                 {
419                         return GetNestedTypes (DefaultBindingFlags);
420                 }
421
422                 public TypeMirror[] GetNestedTypes (BindingFlags bindingAttr) {
423                         if (nested != null)
424                                 return nested;
425
426                         // FIXME: bindingAttr
427                         GetInfo ();
428                         var arr = new TypeMirror [info.nested.Length];
429                         for (int i = 0; i < arr.Length; ++i)
430                                 arr [i] = vm.GetType (info.nested [i]);
431                         nested = arr;
432
433                         return nested;
434                 }
435
436                 public PropertyInfoMirror[] GetProperties () {
437                         return GetProperties (DefaultBindingFlags);
438                 }
439
440                 public PropertyInfoMirror[] GetProperties (BindingFlags bindingAttr) {
441                         if (properties != null)
442                                 return properties;
443
444                         PropInfo[] info = vm.conn.Type_GetProperties (id);
445
446                         PropertyInfoMirror[] res = new PropertyInfoMirror [info.Length];
447                         for (int i = 0; i < res.Length; ++i)
448                                 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);
449
450                         properties = res;
451                         return properties;
452                 }
453
454                 public PropertyInfoMirror GetProperty (string name) {
455                         if (name == null)
456                                 throw new ArgumentNullException ("name");
457                         foreach (var p in GetProperties ())
458                                 if (p.Name == name)
459                                         return p;
460                         return null;
461                 }
462
463                 public virtual bool IsAssignableFrom (TypeMirror c) {
464                         if (c == null)
465                                 throw new ArgumentNullException ("c");
466
467                         CheckMirror (c);
468
469                         // This is complex so do it in the debuggee
470                         return vm.conn.Type_IsAssignableFrom (id, c.Id);
471                 }
472
473                 public Value GetValue (FieldInfoMirror field) {
474                         return GetValues (new FieldInfoMirror [] { field }) [0];
475                 }
476
477                 public Value[] GetValues (IList<FieldInfoMirror> fields, ThreadMirror thread) {
478                         if (fields == null)
479                                 throw new ArgumentNullException ("fields");
480                         foreach (FieldInfoMirror f in fields) {
481                                 if (f == null)
482                                         throw new ArgumentNullException ("field");
483                                 CheckMirror (f);
484                         }
485                         long[] ids = new long [fields.Count];
486                         for (int i = 0; i < fields.Count; ++i)
487                                 ids [i] = fields [i].Id;
488                         try {
489                                 return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread !=  null ? thread.Id : 0));
490                         } catch (CommandException ex) {
491                                 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
492                                         throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
493                                 else
494                                         throw;
495                         }
496                 }
497
498                 public Value[] GetValues (IList<FieldInfoMirror> fields) {
499                         return GetValues (fields, null);
500                 }
501
502                 /*
503                  * Return the value of the [ThreadStatic] field FIELD on the thread THREAD.
504                  */
505                 public Value GetValue (FieldInfoMirror field, ThreadMirror thread) {
506                         if (thread == null)
507                                 throw new ArgumentNullException ("thread");
508                         CheckMirror (thread);
509                         return GetValues (new FieldInfoMirror [] { field }, thread) [0];
510                 }
511
512                 public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
513                         if (fields == null)
514                                 throw new ArgumentNullException ("fields");
515                         if (values == null)
516                                 throw new ArgumentNullException ("values");
517                         foreach (FieldInfoMirror f in fields) {
518                                 if (f == null)
519                                         throw new ArgumentNullException ("field");
520                                 CheckMirror (f);
521                         }
522                         foreach (Value v in values) {
523                                 if (v == null)
524                                         throw new ArgumentNullException ("values");
525                                 CheckMirror (v);
526                         }
527                         long[] ids = new long [fields.Count];
528                         for (int i = 0; i < fields.Count; ++i)
529                                 ids [i] = fields [i].Id;
530                         try {
531                                 vm.conn.Type_SetValues (id, ids, vm.EncodeValues (values));
532                         } catch (CommandException ex) {
533                                 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
534                                         throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
535                                 else
536                                         throw;
537                         }
538                 }
539
540                 public void SetValue (FieldInfoMirror field, Value value) {
541                         SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
542                 }
543
544                 public ObjectMirror GetTypeObject () {
545                         return vm.GetObject (vm.conn.Type_GetObject (id));
546                 }
547
548                 /*
549                  * Return a list of source files without path info, where methods of 
550                  * this type are defined. Return an empty list if the information is not 
551                  * available. 
552                  * This can be used by a debugger to find out which types occur in a 
553                  * given source file, to filter the list of methods whose locations
554                  * have to be checked when placing breakpoints.
555                  */
556                 public string[] GetSourceFiles () {
557                         return GetSourceFiles (false);
558                 }
559
560                 string[] source_files;
561                 string[] source_files_full_path;
562                 public string[] GetSourceFiles (bool return_full_paths) {
563                         string[] res = return_full_paths ? source_files_full_path : source_files;
564                         if (res == null) {
565                                 res = vm.conn.Type_GetSourceFiles (id, return_full_paths);
566                                 if (return_full_paths)
567                                         source_files_full_path = res;
568                                 else
569                                         source_files = res;
570                         }
571                         return res;
572                 }
573
574                 public C.TypeDefinition Metadata {
575                         get {
576                                 if (meta == null) {
577                                         if (Assembly.Metadata == null || MetadataToken == 0)
578                                                 return null;
579                                         meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupToken (MetadataToken);
580                                 }
581                                 return meta;
582                         }
583                 }
584
585                 TypeInfo GetInfo () {
586                         if (info == null)
587                                 info = vm.conn.Type_GetInfo (id);
588                         return info;
589                 }
590
591                 protected virtual TypeAttributes GetAttributeFlagsImpl () {
592                         return (TypeAttributes)GetInfo ().attributes;
593                 }
594
595                 protected virtual bool HasElementTypeImpl () {
596                         return IsArray || IsByRef || IsPointer;
597                 }
598
599                 protected virtual bool IsArrayImpl () {
600                         return GetInfo ().rank > 0;
601                 }
602
603                 protected virtual bool IsByRefImpl () {
604                         return GetInfo ().is_byref;
605                 }
606
607                 protected virtual bool IsCOMObjectImpl () {
608                         return false;
609                 }
610
611                 protected virtual bool IsPointerImpl () {
612                         return GetInfo ().is_pointer;
613                 }
614
615                 protected virtual bool IsPrimitiveImpl () {
616                         return GetInfo ().is_primitive;
617                 }
618
619                 protected virtual bool IsValueTypeImpl ()
620                 {
621                         return GetInfo ().is_valuetype;
622                 }
623                 
624                 protected virtual bool IsContextfulImpl ()
625                 {
626                         // FIXME:
627                         return false;
628                 }
629
630                 protected virtual bool IsMarshalByRefImpl ()
631                 {
632                         // FIXME:
633                         return false;
634                 }
635
636                 // Same as Enum.GetUnderlyingType ()
637                 public TypeMirror EnumUnderlyingType {
638                         get {
639                                 if (!IsEnum)
640                                         throw new ArgumentException ("Type is not an enum type.");
641                                 foreach (FieldInfoMirror f in GetFields ()) {
642                                         if (!f.IsStatic)
643                                                 return f.FieldType;
644                                 }
645                                 throw new NotImplementedException ();
646                         }
647                 }
648
649                 /*
650                  * Creating the custom attributes themselves could modify the behavior of the
651                  * debuggee, so we return objects similar to the CustomAttributeData objects
652                  * used by the reflection-only functionality on .net.
653                  */
654                 public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
655                         return GetCAttrs (null, inherit);
656                 }
657
658                 public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
659                         if (attributeType == null)
660                                 throw new ArgumentNullException ("attributeType");
661                         return GetCAttrs (attributeType, inherit);
662                 }
663
664                 CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
665                         if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
666                                 cattrs = new CustomAttributeDataMirror [0];
667
668                         // FIXME: Handle inherit
669                         if (cattrs == null) {
670                                 CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
671                                 cattrs = CustomAttributeDataMirror.Create (vm, info);
672                         }
673                         var res = new List<CustomAttributeDataMirror> ();
674                         foreach (var attr in cattrs)
675                                 if (type == null || attr.Constructor.DeclaringType == type)
676                                         res.Add (attr);
677                         return res.ToArray ();
678                 }
679
680                 public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
681                         if (vm.conn.Version.AtLeast (2, 6)) {
682                                 long[] ids = vm.conn.Type_GetMethodsByNameFlags (id, name, (int)flags, ignoreCase);
683                                 MethodMirror[] m = new MethodMirror [ids.Length];
684                                 for (int i = 0; i < ids.Length; ++i)
685                                         m [i] = vm.GetMethod (ids [i]);
686                                 return m;
687                         } else {
688                                 if (flags != (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.NonPublic))
689                                         throw new NotImplementedException ();
690                                 var res = new List<MethodMirror> ();
691                                 foreach (MethodMirror m in GetMethods ()) {
692                                         if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase)))
693                                                 res.Add (m);
694                                 }
695                                 return res.ToArray ();
696                         }
697                 }
698
699                 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
700                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
701                 }
702
703                 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
704                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
705                 }
706
707                 [Obsolete ("Use the overload without the 'vm' argument")]
708                 public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
709                         return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
710                 }
711
712                 public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
713                         return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
714                 }
715
716                 public Value EndInvokeMethod (IAsyncResult asyncResult) {
717                         return ObjectMirror.EndInvokeMethodInternal (asyncResult);
718                 }
719
720                 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
721                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
722                 }                       
723
724                 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
725                         return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
726                 }
727
728                 // Since protocol version 2.11
729                 public TypeMirror[] GetInterfaces () {
730                         if (ifaces == null)
731                                 ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id));
732                         return ifaces;
733                 }
734
735                 // Since protocol version 2.11
736                 public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) {
737                         if (interfaceType == null)
738                                 throw new ArgumentNullException ("interfaceType");
739                         if (!interfaceType.IsInterface)
740                                 throw new ArgumentException ("Argument must be an interface.", "interfaceType");
741                         if (IsInterface)
742                                 throw new ArgumentException ("'this' type cannot be an interface itself");
743
744                         if (iface_map == null) {
745                                 // Query the info in bulk
746                                 GetInterfaces ();
747                                 var ids = new long [ifaces.Length];
748                                 for (int i = 0; i < ifaces.Length; ++i)
749                                         ids [i] = ifaces [i].Id;
750
751                                 var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids);
752
753                                 var imap = new Dictionary<TypeMirror, InterfaceMappingMirror> ();
754                                 for (int i = 0; i < ifacemap.Length; ++i) {
755                                         IfaceMapInfo info = ifacemap [i];
756
757                                         MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length];
758                                         for (int j = 0; j < info.iface_methods.Length; ++j)
759                                                 imethods [j] = vm.GetMethod (info.iface_methods [j]);
760
761                                         MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length];
762                                         for (int j = 0; j < info.target_methods.Length; ++j)
763                                                 tmethods [j] = vm.GetMethod (info.target_methods [j]);
764
765                                         InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods);
766
767                                         imap [map.InterfaceType] = map;
768                                 }
769
770                                 iface_map = imap;
771                         }
772
773                         InterfaceMappingMirror res;
774                         if (!iface_map.TryGetValue (interfaceType, out res))
775                                 throw new ArgumentException ("Interface not found", "interfaceType");
776                         return res;
777                 }
778
779     }
780 }