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