using System.Reflection;
using C = Mono.Cecil;
using Mono.Cecil.Metadata;
+#if NET_4_5
+using System.Threading.Tasks;
+#endif
namespace Mono.Debugger.Soft
{
FieldInfoMirror[] fields;
PropertyInfoMirror[] properties;
TypeInfo info;
- TypeMirror base_type, element_type;
+ TypeMirror base_type, element_type, gtd;
TypeMirror[] nested;
CustomAttributeDataMirror[] cattrs;
+ TypeMirror[] ifaces;
+ Dictionary<TypeMirror, InterfaceMappingMirror> iface_map;
+ TypeMirror[] type_args;
+ bool cached_base_type;
+ bool inited;
internal const BindingFlags DefaultBindingFlags =
BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
get {
return GetInfo ().name;
}
- }
+ }
public string Namespace {
get {
return GetInfo ().ns;
}
- }
+ }
public AssemblyMirror Assembly {
get {
public TypeMirror BaseType {
get {
- // FIXME: base_type could be null for object/interfaces
- if (base_type == null) {
+ if (!cached_base_type) {
base_type = vm.GetType (GetInfo ().base_type);
+ cached_base_type = true;
}
return base_type;
}
}
}
+ // Since protocol version 2.12
+ public bool IsGenericTypeDefinition {
+ get {
+ vm.CheckProtocolVersion (2, 12);
+ GetInfo ();
+ return info.is_gtd;
+ }
+ }
+
+ public bool IsGenericType {
+ get {
+ if (vm.Version.AtLeast (2, 12)) {
+ return GetInfo ().is_generic_type;
+ } else {
+ return Name.IndexOf ('`') != -1;
+ }
+ }
+ }
+
public TypeMirror GetElementType () {
GetInfo ();
if (element_type == null && info.element_type != 0)
return element_type;
}
+ public TypeMirror GetGenericTypeDefinition () {
+ vm.CheckProtocolVersion (2, 12);
+ GetInfo ();
+ if (gtd == null) {
+ if (info.gtd == 0)
+ throw new InvalidOperationException ();
+ gtd = vm.GetType (info.gtd);
+ }
+ return gtd;
+ }
+
+ // Since protocol version 2.15
+ public TypeMirror[] GetGenericArguments () {
+ vm.CheckProtocolVersion (2, 15);
+ if (type_args == null)
+ type_args = vm.GetTypes (GetInfo ().type_args);
+ return type_args;
+ }
+
public string FullName {
get {
return GetInfo ().full_name;
switch (Name) {
case "Byte":
return "byte";
+ case "Sbyte":
+ return "sbyte";
+ case "Char":
+ return "char";
+ case "UInt16":
+ return "ushort";
+ case "Int16":
+ return "short";
+ case "UInt32":
+ return "uint";
case "Int32":
return "int";
+ case "UInt64":
+ return "ulong";
+ case "Int64":
+ return "long";
+ case "Single":
+ return "float";
+ case "Double":
+ return "double";
case "Boolean":
return "bool";
default:
if (Namespace == "System") {
string s = Name;
switch (s) {
+ case "Decimal":
+ return "decimal";
+ case "Object":
+ return "object";
case "String":
return "string";
default:
string[] source_files;
string[] source_files_full_path;
- public string[] GetSourceFiles (bool return_full_paths) {
- string[] res = return_full_paths ? source_files_full_path : source_files;
+ public string[] GetSourceFiles (bool returnFullPaths) {
+ string[] res = returnFullPaths ? source_files_full_path : source_files;
if (res == null) {
- res = vm.conn.Type_GetSourceFiles (id, return_full_paths);
- if (return_full_paths)
+ res = vm.conn.Type_GetSourceFiles (id, returnFullPaths);
+ if (returnFullPaths)
source_files_full_path = res;
else
source_files = res;
* used by the reflection-only functionality on .net.
*/
public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
- return GetCAttrs (null, inherit);
+ return GetCustomAttrs (null, inherit);
}
public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
if (attributeType == null)
throw new ArgumentNullException ("attributeType");
- return GetCAttrs (attributeType, inherit);
+ return GetCustomAttrs (attributeType, inherit);
}
- CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
+ void AppendCustomAttrs (IList<CustomAttributeDataMirror> attrs, TypeMirror type, bool inherit)
+ {
if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
cattrs = new CustomAttributeDataMirror [0];
- // FIXME: Handle inherit
if (cattrs == null) {
CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
cattrs = CustomAttributeDataMirror.Create (vm, info);
}
- var res = new List<CustomAttributeDataMirror> ();
- foreach (var attr in cattrs)
+
+ foreach (var attr in cattrs) {
if (type == null || attr.Constructor.DeclaringType == type)
- res.Add (attr);
- return res.ToArray ();
+ attrs.Add (attr);
+ }
+
+ if (inherit && BaseType != null)
+ BaseType.AppendCustomAttrs (attrs, type, inherit);
+ }
+
+ CustomAttributeDataMirror[] GetCustomAttrs (TypeMirror type, bool inherit) {
+ var attrs = new List<CustomAttributeDataMirror> ();
+ AppendCustomAttrs (attrs, type, inherit);
+ return attrs.ToArray ();
}
public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
m [i] = vm.GetMethod (ids [i]);
return m;
} else {
- if (flags != (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.NonPublic))
+ if ((flags & BindingFlags.IgnoreCase) != 0) {
+ flags &= ~BindingFlags.IgnoreCase;
+ ignoreCase = true;
+ }
+
+ if (flags == BindingFlags.Default)
+ flags = BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static;
+
+ MethodAttributes access = (MethodAttributes) 0;
+ bool matchInstance = false;
+ bool matchStatic = false;
+
+ if ((flags & BindingFlags.NonPublic) != 0) {
+ access |= MethodAttributes.Private;
+ flags &= ~BindingFlags.NonPublic;
+ }
+ if ((flags & BindingFlags.Public) != 0) {
+ access |= MethodAttributes.Public;
+ flags &= ~BindingFlags.Public;
+ }
+ if ((flags & BindingFlags.Instance) != 0) {
+ flags &= ~BindingFlags.Instance;
+ matchInstance = true;
+ }
+ if ((flags & BindingFlags.Static) != 0) {
+ flags &= ~BindingFlags.Static;
+ matchStatic = true;
+ }
+
+ if ((int) flags != 0)
throw new NotImplementedException ();
+
var res = new List<MethodMirror> ();
foreach (MethodMirror m in GetMethods ()) {
+ if ((m.Attributes & access) == (MethodAttributes) 0)
+ continue;
+
+ if (!((matchStatic && m.IsStatic) || (matchInstance && !m.IsStatic)))
+ continue;
+
if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase)))
res.Add (m);
}
return ObjectMirror.EndInvokeMethodInternal (asyncResult);
}
+#if NET_4_5
+ public Task<Value> InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) {
+ var tcs = new TaskCompletionSource<Value> ();
+ BeginInvokeMethod (thread, method, arguments, options, iar =>
+ {
+ try {
+ tcs.SetResult (EndInvokeMethod (iar));
+ } catch (OperationCanceledException) {
+ tcs.TrySetCanceled ();
+ } catch (Exception ex) {
+ tcs.TrySetException (ex);
+ }
+ }, null);
+ return tcs.Task;
+ }
+#endif
+
public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
}
public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
- }
+ }
+
+ // Since protocol version 2.11
+ public TypeMirror[] GetInterfaces () {
+ if (ifaces == null)
+ ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id));
+ return ifaces;
+ }
+
+ // Since protocol version 2.11
+ public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) {
+ if (interfaceType == null)
+ throw new ArgumentNullException ("interfaceType");
+ if (!interfaceType.IsInterface)
+ throw new ArgumentException ("Argument must be an interface.", "interfaceType");
+ if (IsInterface)
+ throw new ArgumentException ("'this' type cannot be an interface itself");
+
+ if (iface_map == null) {
+ // Query the info in bulk
+ GetInterfaces ();
+ var ids = new long [ifaces.Length];
+ for (int i = 0; i < ifaces.Length; ++i)
+ ids [i] = ifaces [i].Id;
+
+ var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids);
+
+ var imap = new Dictionary<TypeMirror, InterfaceMappingMirror> ();
+ for (int i = 0; i < ifacemap.Length; ++i) {
+ IfaceMapInfo info = ifacemap [i];
+
+ MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length];
+ for (int j = 0; j < info.iface_methods.Length; ++j)
+ imethods [j] = vm.GetMethod (info.iface_methods [j]);
+
+ MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length];
+ for (int j = 0; j < info.target_methods.Length; ++j)
+ tmethods [j] = vm.GetMethod (info.target_methods [j]);
+
+ InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods);
+
+ imap [map.InterfaceType] = map;
+ }
+
+ iface_map = imap;
+ }
+
+ InterfaceMappingMirror res;
+ if (!iface_map.TryGetValue (interfaceType, out res))
+ throw new ArgumentException ("Interface not found", "interfaceType");
+ return res;
+ }
+
+ // Return whenever the type initializer of this type has ran
+ // Since protocol version 2.23
+ public bool IsInitialized {
+ get {
+ vm.CheckProtocolVersion (2, 23);
+ if (!inited)
+ inited = vm.conn.Type_IsInitialized (id);
+ return inited;
+ }
+ }
}
}