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