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