//
-// System.Reflection/MonoMethod.cs
-// The class used to represent methods from the mono runtime.
+// MonoMethod.cs: The class used to represent methods from the mono runtime.
//
-// Author:
+// Authors:
// Paolo Molaro (lupus@ximian.com)
+// Marek Safar (marek.safar@gmail.com)
//
// (C) 2001 Ximian, Inc. http://www.ximian.com
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
+#if !FULL_AOT_RUNTIME
using System.Reflection.Emit;
+#endif
using System.Security;
+using System.Threading;
+using System.Text;
+using System.Diagnostics;
namespace System.Reflection {
internal struct MonoMethodInfo
{
- internal Type parent;
- internal Type ret;
+#pragma warning disable 649
+ private Type parent;
+ private Type ret;
internal MethodAttributes attrs;
internal MethodImplAttributes iattrs;
- internal CallingConventions callconv;
+ private CallingConventions callconv;
+#pragma warning restore 649
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
+ static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern ParameterInfo[] get_parameter_info (IntPtr handle);
+ static extern int get_method_attributes (IntPtr handle);
+
+ internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
+ {
+ MonoMethodInfo info;
+ MonoMethodInfo.get_method_info (handle, out info);
+ return info;
+ }
+
+ internal static Type GetDeclaringType (IntPtr handle)
+ {
+ return GetMethodInfo (handle).parent;
+ }
+
+ internal static Type GetReturnType (IntPtr handle)
+ {
+ return GetMethodInfo (handle).ret;
+ }
+
+ internal static MethodAttributes GetAttributes (IntPtr handle)
+ {
+ return (MethodAttributes)get_method_attributes (handle);
+ }
+
+ internal static CallingConventions GetCallingConvention (IntPtr handle)
+ {
+ return GetMethodInfo (handle).callconv;
+ }
+
+ internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
+ {
+ return GetMethodInfo (handle).iattrs;
+ }
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
+ static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
+
+ static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
+ {
+ return get_parameter_info (handle, member);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
+
+ static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
+ {
+ return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
+ }
};
/*
* the .NET reflection class hierarchy is so broken.
*/
[Serializable()]
+ [StructLayout (LayoutKind.Sequential)]
internal class MonoMethod : MethodInfo, ISerializable
{
+#pragma warning disable 649
internal IntPtr mhandle;
string name;
Type reftype;
+#pragma warning restore 649
internal MonoMethod () {
}
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern MonoMethod get_base_definition (MonoMethod method);
+ internal static extern string get_name (MethodBase method);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
public override MethodInfo GetBaseDefinition ()
{
- return get_base_definition (this);
+ return get_base_method (this, true);
+ }
+
+ internal override MethodInfo GetBaseMethod ()
+ {
+ return get_base_method (this, false);
}
-#if NET_2_0 || BOOTSTRAP_NET_2_0
public override ParameterInfo ReturnParameter {
get {
- return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
+ return MonoMethodInfo.GetReturnParameterInfo (this);
}
}
-#endif
public override Type ReturnType {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.ret;
+ return MonoMethodInfo.GetReturnType (mhandle);
}
}
public override ICustomAttributeProvider ReturnTypeCustomAttributes {
get {
- return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
+ return MonoMethodInfo.GetReturnParameterInfo (this);
}
}
- public override MethodImplAttributes GetMethodImplementationFlags() {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.iattrs;
+ public override MethodImplAttributes GetMethodImplementationFlags ()
+ {
+ return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
}
- public override ParameterInfo[] GetParameters() {
- return MonoMethodInfo.get_parameter_info (mhandle);
+ public override ParameterInfo[] GetParameters ()
+ {
+ ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
+ ParameterInfo[] res = new ParameterInfo [src.Length];
+ src.CopyTo (res, 0);
+ return res;
+ }
+
+ internal override int GetParameterCount ()
+ {
+ var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
+ return pi == null ? 0 : pi.Length;
}
/*
* binder to match the types of the method signature.
*/
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern Object InternalInvoke (Object obj, Object[] parameters);
-
+ internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
+
+ [DebuggerHidden]
+ [DebuggerStepThrough]
public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
{
if (binder == null)
binder = Binder.DefaultBinder;
- ParameterInfo[] pinfo = GetParameters ();
- if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
- throw new ArgumentException ("parameters");
+ /*Avoid allocating an array every time*/
+ ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
+ if (!binder.ConvertArgs (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0))
+ throw new ArgumentException ("failed to convert parameters");
+
+#if !NET_2_1
if (SecurityManager.SecurityEnabled) {
// sadly Attributes doesn't tell us which kind of security action this is so
// we must do it the hard way - and it also means that we can skip calling
// Attribute (which is another an icall)
SecurityManager.ReflectedLinkDemandInvoke (this);
}
+#endif
-#if NET_2_0
if (ContainsGenericParameters)
throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
-#endif
+
+ Exception exc;
+ object o = null;
try {
- return InternalInvoke (obj, parameters);
- } catch (InvalidOperationException) {
+ // The ex argument is used to distinguish exceptions thrown by the icall
+ // from the exceptions thrown by the called method (which need to be
+ // wrapped in TargetInvocationException).
+ o = InternalInvoke (obj, parameters, out exc);
+ } catch (ThreadAbortException) {
throw;
- } catch (TargetException) {
+#if NET_2_1
+ } catch (MethodAccessException) {
throw;
+#endif
} catch (Exception e) {
throw new TargetInvocationException (e);
}
+
+ if (exc != null)
+ throw exc;
+ return o;
}
public override RuntimeMethodHandle MethodHandle {
- get {return new RuntimeMethodHandle (mhandle);}
+ get {
+ return new RuntimeMethodHandle (mhandle);
+ }
}
+
public override MethodAttributes Attributes {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.attrs;
+ return MonoMethodInfo.GetAttributes (mhandle);
}
}
public override CallingConventions CallingConvention {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.callconv;
+ return MonoMethodInfo.GetCallingConvention (mhandle);
}
}
}
public override Type DeclaringType {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.parent;
+ return MonoMethodInfo.GetDeclaringType (mhandle);
}
}
public override string Name {
get {
- return name;
+ if (name != null)
+ return name;
+ return get_name (this);
}
}
/* MS.NET doesn't report MethodImplAttribute */
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
+ MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
count ++;
if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
return attrs;
}
+ static bool ShouldPrintFullName (Type type) {
+ return type.IsClass && (!type.IsPointer ||
+ (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
+ }
+
public override string ToString () {
- string parms = "";
+ StringBuilder sb = new StringBuilder ();
+ Type retType = ReturnType;
+ if (ShouldPrintFullName (retType))
+ sb.Append (retType.ToString ());
+ else
+ sb.Append (retType.Name);
+ sb.Append (" ");
+ sb.Append (Name);
+ if (IsGenericMethod) {
+ Type[] gen_params = GetGenericArguments ();
+ sb.Append ("[");
+ for (int j = 0; j < gen_params.Length; j++) {
+ if (j > 0)
+ sb.Append (",");
+ sb.Append (gen_params [j].Name);
+ }
+ sb.Append ("]");
+ }
+ sb.Append ("(");
ParameterInfo[] p = GetParameters ();
for (int i = 0; i < p.Length; ++i) {
if (i > 0)
- parms = parms + ", ";
+ sb.Append (", ");
Type pt = p[i].ParameterType;
bool byref = pt.IsByRef;
if (byref)
pt = pt.GetElementType ();
- if (pt.IsClass && pt.Namespace != "")
- parms = parms + pt.Namespace + "." + pt.Name;
+ if (ShouldPrintFullName (pt))
+ sb.Append (pt.ToString ());
else
- parms = parms + pt.Name;
+ sb.Append (pt.Name);
if (byref)
- parms += " ByRef";
+ sb.Append (" ByRef");
}
- if (ReturnType.IsClass && ReturnType.Namespace != "")
- return ReturnType.Namespace + "." + ReturnType.Name + " " + Name + "(" + parms + ")";
- string generic = "";
-#if NET_2_0 || BOOTSTRAP_NET_2_0
- if (IsGenericMethod) {
- Type[] gen_params = GetGenericArguments ();
- generic = "[";
- for (int j = 0; j < gen_params.Length; j++) {
- if (j > 0)
- generic += ",";
- generic += gen_params [j].Name;
- }
- generic += "]";
+ if ((CallingConvention & CallingConventions.VarArgs) != 0) {
+ if (p.Length > 0)
+ sb.Append (", ");
+ sb.Append ("...");
}
-#endif
- return ReturnType.Name + " " + Name + generic + "(" + parms + ")";
+
+ sb.Append (")");
+ return sb.ToString ();
}
// ISerializable
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
- ReflectionSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
+ Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
+ ? GetGenericArguments () : null;
+ MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
}
-#if NET_2_0 || BOOTSTRAP_NET_2_0
- public override MethodInfo MakeGenericMethod (Type [] types)
+ public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
{
- if (types == null)
- throw new ArgumentNullException ("types");
- MethodInfo ret = MakeGenericMethod_impl (types);
+ if (methodInstantiation == null)
+ throw new ArgumentNullException ("methodInstantiation");
+
+ if (!IsGenericMethodDefinition)
+ throw new InvalidOperationException ("not a generic method definition");
+
+ /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
+ if (GetGenericArguments ().Length != methodInstantiation.Length)
+ throw new ArgumentException ("Incorrect length");
+
+ bool hasUserType = false;
+ foreach (Type type in methodInstantiation) {
+ if (type == null)
+ throw new ArgumentNullException ();
+ if (!(type is MonoType))
+ hasUserType = true;
+ }
+
+#if !FULL_AOT_RUNTIME
+ if (hasUserType)
+ return new MethodOnTypeBuilderInst (this, methodInstantiation);
+#endif
+
+ MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
if (ret == null)
- throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, types.Length));
+ throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
return ret;
}
return DeclaringType.ContainsGenericParameters;
}
}
-#endif
-#if NET_2_0
public override MethodBody GetMethodBody () {
return GetMethodBody (mhandle);
}
+
+#if NET_4_0
+ public override IList<CustomAttributeData> GetCustomAttributesData () {
+ return CustomAttributeData.GetCustomAttributes (this);
+ }
#endif
}
+ [StructLayout (LayoutKind.Sequential)]
internal class MonoCMethod : ConstructorInfo, ISerializable
{
+#pragma warning disable 649
internal IntPtr mhandle;
string name;
Type reftype;
+#pragma warning restore 649
- public override MethodImplAttributes GetMethodImplementationFlags() {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.iattrs;
+ public override MethodImplAttributes GetMethodImplementationFlags ()
+ {
+ return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
+ }
+
+ public override ParameterInfo[] GetParameters ()
+ {
+ return MonoMethodInfo.GetParametersInfo (mhandle, this);
}
- public override ParameterInfo[] GetParameters() {
- return MonoMethodInfo.get_parameter_info (mhandle);
+ internal override int GetParameterCount ()
+ {
+ var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
+ return pi == null ? 0 : pi.Length;
}
/*
* to match the types of the method signature.
*/
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern Object InternalInvoke (Object obj, Object[] parameters);
+ internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
+ [DebuggerHidden]
+ [DebuggerStepThrough]
public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
{
if (binder == null)
binder = Binder.DefaultBinder;
- ParameterInfo[] pinfo = GetParameters ();
- if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
- throw new ArgumentException ("parameters");
+ ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
+
+ if (!binder.ConvertArgs (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0))
+ throw new ArgumentException ("failed to convert parameters");
+
+#if !NET_2_1
if (SecurityManager.SecurityEnabled) {
// sadly Attributes doesn't tell us which kind of security action this is so
// we must do it the hard way - and it also means that we can skip calling
// Attribute (which is another an icall)
SecurityManager.ReflectedLinkDemandInvoke (this);
}
+#endif
+
+ if (obj == null && DeclaringType.ContainsGenericParameters)
+ throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
+
+ if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
+ throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
+ }
+
+ Exception exc = null;
+ object o = null;
try {
- return InternalInvoke (obj, parameters);
- } catch (InvalidOperationException) {
- throw;
- } catch (TargetException) {
+ o = InternalInvoke (obj, parameters, out exc);
+#if NET_2_1
+ } catch (MethodAccessException) {
throw;
+#endif
} catch (Exception e) {
throw new TargetInvocationException (e);
}
+
+ if (exc != null)
+ throw exc;
+ return (obj == null) ? o : null;
}
- public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
+ [DebuggerHidden]
+ [DebuggerStepThrough]
+ public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
return Invoke (null, invokeAttr, binder, parameters, culture);
}
public override RuntimeMethodHandle MethodHandle {
- get {return new RuntimeMethodHandle (mhandle);}
+ get {
+ return new RuntimeMethodHandle (mhandle);
+ }
}
+
public override MethodAttributes Attributes {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.attrs;
+ return MonoMethodInfo.GetAttributes (mhandle);
}
}
public override CallingConventions CallingConvention {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.callconv;
+ return MonoMethodInfo.GetCallingConvention (mhandle);
}
}
}
public override Type DeclaringType {
get {
- MonoMethodInfo info;
- MonoMethodInfo.get_method_info (mhandle, out info);
- return info.parent;
+ return MonoMethodInfo.GetDeclaringType (mhandle);
}
}
public override string Name {
get {
- return name;
+ if (name != null)
+ return name;
+ return MonoMethod.get_name (this);
}
}
return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
}
-#if NET_2_0 || BOOTSTRAP_NET_2_0
- public override bool IsGenericMethodDefinition {
- get {
- return false;
- }
- }
-
- public override bool IsGenericMethod {
- get {
- return false;
- }
- }
-#endif
-
-#if NET_2_0
public override MethodBody GetMethodBody () {
return GetMethodBody (mhandle);
}
-#endif
public override string ToString () {
- string parms = "";
+ StringBuilder sb = new StringBuilder ();
+ sb.Append ("Void ");
+ sb.Append (Name);
+ sb.Append ("(");
ParameterInfo[] p = GetParameters ();
for (int i = 0; i < p.Length; ++i) {
if (i > 0)
- parms = parms + ", ";
- parms = parms + p [i].ParameterType.Name;
+ sb.Append (", ");
+ sb.Append (p[i].ParameterType.Name);
}
- return "Void "+Name+"("+parms+")";
+ if (CallingConvention == CallingConventions.Any)
+ sb.Append (", ...");
+ sb.Append (")");
+ return sb.ToString ();
}
// ISerializable
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
- ReflectionSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
+ MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
}
+
+#if NET_4_0
+ public override IList<CustomAttributeData> GetCustomAttributesData () {
+ return CustomAttributeData.GetCustomAttributes (this);
+ }
+#endif
}
}