// 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;
using System.Security;
namespace System.Reflection {
internal struct MonoPropertyInfo {
public Type parent;
+ public Type declaring_type;
public String name;
public MethodInfo get_method;
public MethodInfo set_method;
public PropertyAttributes attrs;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern void get_property_info (MonoProperty prop, out MonoPropertyInfo info,
+ internal static extern void get_property_info (MonoProperty prop, ref MonoPropertyInfo info,
PInfo req_info);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal static extern Type[] GetTypeModifiers (MonoProperty prop, bool optional);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal static extern object get_default_value (MonoProperty prop);
}
[Flags]
Name = 1 << 5
}
- internal class MonoProperty : PropertyInfo {
+
+ internal delegate object GetterAdapter (object _this);
+ internal delegate R Getter<T,R> (T _this);
+
+ [Serializable]
+ [StructLayout (LayoutKind.Sequential)]
+ internal class MonoProperty : PropertyInfo, ISerializable {
+#pragma warning disable 649
internal IntPtr klass;
internal IntPtr prop;
+ MonoPropertyInfo info;
+ PInfo cached;
+ GetterAdapter cached_getter;
+
+#pragma warning restore 649
+
+ void CachePropertyInfo (PInfo flags)
+ {
+ if ((cached & flags) != flags) {
+ MonoPropertyInfo.get_property_info (this, ref info, flags);
+ cached |= flags;
+ }
+ }
public override PropertyAttributes Attributes {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.Attributes);
+ CachePropertyInfo (PInfo.Attributes);
return info.attrs;
}
}
public override bool CanRead {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod);
+ CachePropertyInfo (PInfo.GetMethod);
return (info.get_method != null);
}
}
public override bool CanWrite {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.SetMethod);
+ CachePropertyInfo (PInfo.SetMethod);
return (info.set_method != null);
}
}
public override Type PropertyType {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod | PInfo.SetMethod);
-
+ CachePropertyInfo (PInfo.GetMethod | PInfo.SetMethod);
+
if (info.get_method != null) {
return info.get_method.ReturnType;
} else {
- ParameterInfo[] parameters = info.set_method.GetParameters();
+ ParameterInfo[] parameters = info.set_method.GetParameters ();
return parameters [parameters.Length - 1].ParameterType;
}
public override Type ReflectedType {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.ReflectedType);
+ CachePropertyInfo (PInfo.ReflectedType);
return info.parent;
}
}
public override Type DeclaringType {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.DeclaringType);
- return info.parent;
+ CachePropertyInfo (PInfo.DeclaringType);
+ return info.declaring_type;
}
}
public override string Name {
get {
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.Name);
+ CachePropertyInfo (PInfo.Name);
return info.name;
}
}
public override MethodInfo[] GetAccessors (bool nonPublic)
{
- MonoPropertyInfo info;
int nget = 0;
int nset = 0;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod | PInfo.SetMethod);
+ CachePropertyInfo (PInfo.GetMethod | PInfo.SetMethod);
+
if (info.set_method != null && (nonPublic || info.set_method.IsPublic))
nset = 1;
if (info.get_method != null && (nonPublic || info.get_method.IsPublic))
public override MethodInfo GetGetMethod (bool nonPublic)
{
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod);
+ CachePropertyInfo (PInfo.GetMethod);
if (info.get_method != null && (nonPublic || info.get_method.IsPublic))
return info.get_method;
else
public override ParameterInfo[] GetIndexParameters()
{
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.GetMethod);
- if (info.get_method != null)
- return info.get_method.GetParameters ();
- return new ParameterInfo [0];
+ CachePropertyInfo (PInfo.GetMethod | PInfo.SetMethod);
+ ParameterInfo[] res;
+ if (info.get_method != null) {
+ res = info.get_method.GetParameters ();
+ } else if (info.set_method != null) {
+ ParameterInfo[] src = info.set_method.GetParameters ();
+ res = new ParameterInfo [src.Length - 1];
+ Array.Copy (src, res, res.Length);
+ } else
+ return new ParameterInfo [0];
+
+ for (int i = 0; i < res.Length; ++i) {
+ ParameterInfo pinfo = res [i];
+ res [i] = new ParameterInfo (pinfo, this);
+ }
+ return res;
}
public override MethodInfo GetSetMethod (bool nonPublic)
{
- MonoPropertyInfo info;
- MonoPropertyInfo.get_property_info (this, out info, PInfo.SetMethod);
+ CachePropertyInfo (PInfo.SetMethod);
if (info.set_method != null && (nonPublic || info.set_method.IsPublic))
return info.set_method;
else
return null;
}
-
+
+
+ /*TODO verify for attribute based default values, just like ParameterInfo*/
+ public override object GetConstantValue ()
+ {
+ return MonoPropertyInfo.get_default_value (this);
+ }
+
+ public override object GetRawConstantValue() {
+ return MonoPropertyInfo.get_default_value (this);
+ }
+
+ // According to MSDN the inherit parameter is ignored here and
+ // the behavior always defaults to inherit = false
+ //
public override bool IsDefined (Type attributeType, bool inherit)
{
- return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
+ return MonoCustomAttrs.IsDefined (this, attributeType, false);
}
public override object[] GetCustomAttributes (bool inherit)
{
- return MonoCustomAttrs.GetCustomAttributes (this, inherit);
+ return MonoCustomAttrs.GetCustomAttributes (this, false);
}
public override object[] GetCustomAttributes (Type attributeType, bool inherit)
{
- return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
+ return MonoCustomAttrs.GetCustomAttributes (this, attributeType, false);
+ }
+
+
+ delegate object GetterAdapter (object _this);
+ delegate R Getter<T,R> (T _this);
+ delegate R StaticGetter<R> ();
+
+#pragma warning disable 169
+ // Used via reflection
+ static object GetterAdapterFrame<T,R> (Getter<T,R> getter, object obj)
+ {
+ return getter ((T)obj);
+ }
+
+ static object StaticGetterAdapterFrame<R> (StaticGetter<R> getter, object obj)
+ {
+ return getter ();
+ }
+#pragma warning restore 169
+
+ /*
+ * The idea behing this optimization is to use a pair of delegates to simulate the same effect of doing a reflection call.
+ * The first delegate cast the this argument to the right type and the second does points to the target method.
+ */
+ static GetterAdapter CreateGetterDelegate (MethodInfo method)
+ {
+ Type[] typeVector;
+ Type getterType;
+ object getterDelegate;
+ MethodInfo adapterFrame;
+ Type getterDelegateType;
+ string frameName;
+
+ if (method.IsStatic) {
+ typeVector = new Type[] { method.ReturnType };
+ getterDelegateType = typeof (StaticGetter<>);
+ frameName = "StaticGetterAdapterFrame";
+ } else {
+ typeVector = new Type[] { method.DeclaringType, method.ReturnType };
+ getterDelegateType = typeof (Getter<,>);
+ frameName = "GetterAdapterFrame";
+ }
+
+ getterType = getterDelegateType.MakeGenericType (typeVector);
+#if NET_2_1
+ // with Silverlight a coreclr failure (e.g. Transparent caller creating a delegate on a Critical method)
+ // would normally throw an ArgumentException, so we set throwOnBindFailure to false and check for a null
+ // delegate that we can transform into a MethodAccessException
+ getterDelegate = Delegate.CreateDelegate (getterType, method, false);
+ if (getterDelegate == null)
+ throw new MethodAccessException ();
+#else
+ getterDelegate = Delegate.CreateDelegate (getterType, method);
+#endif
+ adapterFrame = typeof (MonoProperty).GetMethod (frameName, BindingFlags.Static | BindingFlags.NonPublic);
+ adapterFrame = adapterFrame.MakeGenericMethod (typeVector);
+ return (GetterAdapter)Delegate.CreateDelegate (typeof (GetterAdapter), getterDelegate, adapterFrame, true);
+ }
+
+ public override object GetValue (object obj, object[] index)
+ {
+ if (index == null || index.Length == 0) {
+ /*FIXME we should check if the number of arguments matches the expected one, otherwise the error message will be pretty criptic.*/
+#if !MONOTOUCH
+ if (cached_getter == null) {
+ MethodInfo method = GetGetMethod (true);
+ if (!DeclaringType.IsValueType && !method.ContainsGenericParameters) { //FIXME find a way to build an invoke delegate for value types.
+ if (method == null)
+ throw new ArgumentException ("Get Method not found for '" + Name + "'");
+ cached_getter = CreateGetterDelegate (method);
+ // The try-catch preserves the .Invoke () behaviour
+ try {
+ return cached_getter (obj);
+ } catch (Exception ex) {
+ throw new TargetInvocationException (ex);
+ }
+ }
+ } else {
+ try {
+ return cached_getter (obj);
+ } catch (Exception ex) {
+ throw new TargetInvocationException (ex);
+ }
+ }
+#endif
+ }
+
+ return GetValue (obj, BindingFlags.Default, null, index, null);
}
public override object GetValue (object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
public override string ToString () {
return PropertyType.ToString () + " " + Name;
}
+
+ public override Type[] GetOptionalCustomModifiers () {
+ Type[] types = MonoPropertyInfo.GetTypeModifiers (this, true);
+ if (types == null)
+ return Type.EmptyTypes;
+ return types;
+ }
+
+ public override Type[] GetRequiredCustomModifiers () {
+ Type[] types = MonoPropertyInfo.GetTypeModifiers (this, false);
+ if (types == null)
+ return Type.EmptyTypes;
+ return types;
+ }
+
+ // ISerializable
+ public void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ MemberInfoSerializationHolder.Serialize (info, Name, ReflectedType,
+ ToString(), MemberTypes.Property);
+ }
+
+#if NET_4_0
+ public override IList<CustomAttributeData> GetCustomAttributesData () {
+ return CustomAttributeData.GetCustomAttributes (this);
+ }
+#endif
}
}
-