2 using System
.Collections
.Generic
;
3 using System
.Globalization
;
4 using System
.Runtime
.CompilerServices
;
5 using System
.Runtime
.InteropServices
;
9 namespace System
.Reflection
11 internal struct MonoPropertyInfo
{
13 public Type declaring_type
;
15 public MethodInfo get_method
;
16 public MethodInfo set_method
;
17 public PropertyAttributes attrs
;
25 ReflectedType
= 1 << 3,
26 DeclaringType
= 1 << 4,
31 internal delegate object GetterAdapter (object _this
);
32 internal delegate R Getter
<T
,R
> (T _this
);
34 [StructLayout (LayoutKind
.Sequential
)]
35 internal class RuntimePropertyInfo
: PropertyInfo
37 #pragma warning disable 649
38 internal IntPtr klass
;
40 MonoPropertyInfo info
;
42 GetterAdapter cached_getter
;
43 #pragma warning restore 649
45 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
46 internal static extern void get_property_info (RuntimePropertyInfo prop
, ref MonoPropertyInfo info
,
49 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
50 internal static extern Type
[] GetTypeModifiers (RuntimePropertyInfo prop
, bool optional
);
52 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
53 internal static extern object get_default_value (RuntimePropertyInfo prop
);
56 internal BindingFlags BindingFlags
{
58 CachePropertyInfo (PInfo
.GetMethod
| PInfo
.SetMethod
);
59 bool isPublic
= info
.set_method
?.IsPublic
== true || info
.get_method
?.IsPublic
== true;
60 bool isStatic
= info
.set_method
?.IsStatic
== true || info
.get_method
?.IsStatic
== true;
61 bool isInherited
= DeclaringType
!= ReflectedType
;
62 return FilterPreCalculate (isPublic
, isInherited
, isStatic
);
66 // Copied from https://github.com/dotnet/coreclr/blob/7a24a538cd265993e5864179f51781398c28ecdf/src/System.Private.CoreLib/src/System/RtType.cs#L2022
67 static BindingFlags
FilterPreCalculate (bool isPublic
, bool isInherited
, bool isStatic
)
69 BindingFlags bindingFlags
= isPublic
? BindingFlags
.Public
: BindingFlags
.NonPublic
;
71 // We arrange things so the DeclaredOnly flag means "include inherited members"
72 bindingFlags
|= BindingFlags
.DeclaredOnly
;
74 bindingFlags
|= BindingFlags
.Static
| BindingFlags
.FlattenHierarchy
;
76 bindingFlags
|= BindingFlags
.Instance
;
80 bindingFlags
|= BindingFlags
.Static
;
82 bindingFlags
|= BindingFlags
.Instance
;
87 public override Module Module
{
89 return GetRuntimeModule ();
93 internal RuntimeType
GetDeclaringTypeInternal ()
95 return (RuntimeType
) DeclaringType
;
98 RuntimeType ReflectedTypeInternal
{
100 return (RuntimeType
) ReflectedType
;
104 internal RuntimeModule
GetRuntimeModule ()
106 return GetDeclaringTypeInternal ().GetRuntimeModule ();
109 #region Object Overrides
110 public override String
ToString()
112 return FormatNameAndSig(false);
115 private string FormatNameAndSig(bool serialization
)
117 StringBuilder sbName
= new StringBuilder(PropertyType
.FormatTypeName(serialization
));
122 var pi
= GetIndexParameters ();
124 sbName
.Append (" [");
125 RuntimeParameterInfo
.FormatParameters (sbName
, pi
, 0, serialization
);
129 return sbName
.ToString();
133 void CachePropertyInfo (PInfo flags
)
135 if ((cached
& flags
) != flags
) {
136 get_property_info (this, ref info
, flags
);
141 public override PropertyAttributes Attributes
{
143 CachePropertyInfo (PInfo
.Attributes
);
148 public override bool CanRead
{
150 CachePropertyInfo (PInfo
.GetMethod
);
151 return (info
.get_method
!= null);
155 public override bool CanWrite
{
157 CachePropertyInfo (PInfo
.SetMethod
);
158 return (info
.set_method
!= null);
162 public override Type PropertyType
{
164 CachePropertyInfo (PInfo
.GetMethod
| PInfo
.SetMethod
);
166 if (info
.get_method
!= null) {
167 return info
.get_method
.ReturnType
;
169 ParameterInfo
[] parameters
= info
.set_method
.GetParametersInternal ();
171 return parameters
[parameters
.Length
- 1].ParameterType
;
176 public override Type ReflectedType
{
178 CachePropertyInfo (PInfo
.ReflectedType
);
183 public override Type DeclaringType
{
185 CachePropertyInfo (PInfo
.DeclaringType
);
186 return info
.declaring_type
;
190 public override string Name
{
192 CachePropertyInfo (PInfo
.Name
);
197 public override MethodInfo
[] GetAccessors (bool nonPublic
)
202 CachePropertyInfo (PInfo
.GetMethod
| PInfo
.SetMethod
);
204 if (info
.set_method
!= null && (nonPublic
|| info
.set_method
.IsPublic
))
206 if (info
.get_method
!= null && (nonPublic
|| info
.get_method
.IsPublic
))
209 MethodInfo
[] res
= new MethodInfo
[nget
+ nset
];
212 res
[n
++] = info
.set_method
;
214 res
[n
++] = info
.get_method
;
218 public override MethodInfo
GetGetMethod (bool nonPublic
)
220 CachePropertyInfo (PInfo
.GetMethod
);
221 if (info
.get_method
!= null && (nonPublic
|| info
.get_method
.IsPublic
))
222 return info
.get_method
;
227 public override ParameterInfo
[] GetIndexParameters ()
229 CachePropertyInfo (PInfo
.GetMethod
| PInfo
.SetMethod
);
232 if (info
.get_method
!= null) {
233 src
= info
.get_method
.GetParametersInternal ();
235 } else if (info
.set_method
!= null) {
236 src
= info
.set_method
.GetParametersInternal ();
237 length
= src
.Length
- 1;
239 return Array
.Empty
<ParameterInfo
> ();
241 var dest
= new ParameterInfo
[length
];
242 for (int i
= 0; i
< length
; ++i
) {
243 dest
[i
] = RuntimeParameterInfo
.New (src
[i
], this);
248 public override MethodInfo
GetSetMethod (bool nonPublic
)
250 CachePropertyInfo (PInfo
.SetMethod
);
251 if (info
.set_method
!= null && (nonPublic
|| info
.set_method
.IsPublic
))
252 return info
.set_method
;
258 /*TODO verify for attribute based default values, just like ParameterInfo*/
259 public override object GetConstantValue ()
261 return get_default_value (this);
264 public override object GetRawConstantValue() {
265 return get_default_value (this);
268 // According to MSDN the inherit parameter is ignored here and
269 // the behavior always defaults to inherit = false
271 public override bool IsDefined (Type attributeType
, bool inherit
)
273 return MonoCustomAttrs
.IsDefined (this, attributeType
, false);
276 public override object[] GetCustomAttributes (bool inherit
)
278 return MonoCustomAttrs
.GetCustomAttributes (this, false);
281 public override object[] GetCustomAttributes (Type attributeType
, bool inherit
)
283 return MonoCustomAttrs
.GetCustomAttributes (this, attributeType
, false);
287 delegate object GetterAdapter (object _this
);
288 delegate R Getter
<T
,R
> (T _this
);
289 delegate R StaticGetter
<R
> ();
291 #pragma warning disable 169
292 // Used via reflection
293 static object GetterAdapterFrame
<T
,R
> (Getter
<T
,R
> getter
, object obj
)
295 return getter ((T
)obj
);
298 static object StaticGetterAdapterFrame
<R
> (StaticGetter
<R
> getter
, object obj
)
302 #pragma warning restore 169
305 * The idea behing this optimization is to use a pair of delegates to simulate the same effect of doing a reflection call.
306 * The first delegate cast the this argument to the right type and the second does points to the target method.
308 static GetterAdapter
CreateGetterDelegate (MethodInfo method
)
312 object getterDelegate
;
313 MethodInfo adapterFrame
;
314 Type getterDelegateType
;
317 if (method
.IsStatic
) {
318 typeVector
= new Type
[] { method.ReturnType }
;
319 getterDelegateType
= typeof (StaticGetter
<>);
320 frameName
= "StaticGetterAdapterFrame";
322 typeVector
= new Type
[] { method.DeclaringType, method.ReturnType }
;
323 getterDelegateType
= typeof (Getter
<,>);
324 frameName
= "GetterAdapterFrame";
327 getterType
= getterDelegateType
.MakeGenericType (typeVector
);
328 getterDelegate
= Delegate
.CreateDelegate (getterType
, method
);
329 adapterFrame
= typeof (RuntimePropertyInfo
).GetMethod (frameName
, BindingFlags
.Static
| BindingFlags
.NonPublic
);
330 adapterFrame
= adapterFrame
.MakeGenericMethod (typeVector
);
331 return (GetterAdapter
)Delegate
.CreateDelegate (typeof (GetterAdapter
), getterDelegate
, adapterFrame
, true);
334 public override object GetValue (object obj
, object[] index
)
336 if (index
== null || index
.Length
== 0) {
337 /*FIXME we should check if the number of arguments matches the expected one, otherwise the error message will be pretty criptic.*/
338 #if !FULL_AOT_RUNTIME
339 if (cached_getter
== null) {
340 MethodInfo method
= GetGetMethod (true);
342 throw new ArgumentException ($"Get Method not found for '{Name}'");
343 if (!DeclaringType
.IsValueType
&& !PropertyType
.IsByRef
&& !method
.ContainsGenericParameters
) { //FIXME find a way to build an invoke delegate for value types.
344 cached_getter
= CreateGetterDelegate (method
);
345 // The try-catch preserves the .Invoke () behaviour
347 return cached_getter (obj
);
348 } catch (Exception ex
) {
349 throw new TargetInvocationException (ex
);
354 return cached_getter (obj
);
355 } catch (Exception ex
) {
356 throw new TargetInvocationException (ex
);
362 return GetValue (obj
, BindingFlags
.Default
, null, index
, null);
365 public override object GetValue (object obj
, BindingFlags invokeAttr
, Binder binder
, object[] index
, CultureInfo culture
)
369 MethodInfo method
= GetGetMethod (true);
371 throw new ArgumentException ($"Get Method not found for '{Name}'");
373 if (index
== null || index
.Length
== 0)
374 ret
= method
.Invoke (obj
, invokeAttr
, binder
, null, culture
);
376 ret
= method
.Invoke (obj
, invokeAttr
, binder
, index
, culture
);
381 public override void SetValue (object obj
, object value, BindingFlags invokeAttr
, Binder binder
, object[] index
, CultureInfo culture
)
383 MethodInfo method
= GetSetMethod (true);
385 throw new ArgumentException ("Set Method not found for '" + Name
+ "'");
388 if (index
== null || index
.Length
== 0)
389 parms
= new object [] {value}
;
391 int ilen
= index
.Length
;
392 parms
= new object [ilen
+ 1];
393 index
.CopyTo (parms
, 0);
394 parms
[ilen
] = value;
397 method
.Invoke (obj
, invokeAttr
, binder
, parms
, culture
);
400 public override Type
[] GetOptionalCustomModifiers () => GetCustomModifiers (true);
402 public override Type
[] GetRequiredCustomModifiers () => GetCustomModifiers (false);
404 private Type
[] GetCustomModifiers (bool optional
) => GetTypeModifiers (this, optional
) ?? Type
.EmptyTypes
;
406 public override IList
<CustomAttributeData
> GetCustomAttributesData () {
407 return CustomAttributeData
.GetCustomAttributes (this);
410 public sealed override bool HasSameMetadataDefinitionAs (MemberInfo other
) => HasSameMetadataDefinitionAsCore
<RuntimePropertyInfo
> (other
);
412 public override int MetadataToken
{
414 return get_metadata_token (this);
418 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
419 internal static extern int get_metadata_token (RuntimePropertyInfo monoProperty
);
421 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
422 private static extern PropertyInfo
internal_from_handle_type (IntPtr event_handle
, IntPtr type_handle
);
424 internal static PropertyInfo
GetPropertyFromHandle (RuntimePropertyHandle handle
, RuntimeTypeHandle reflectedType
)
426 if (handle
.Value
== IntPtr
.Zero
)
427 throw new ArgumentException ("The handle is invalid.");
428 PropertyInfo pi
= internal_from_handle_type (handle
.Value
, reflectedType
.Value
);
430 throw new ArgumentException ("The property handle and the type handle are incompatible.");