[System.Private.CoreLib] Remove unused members and further cleanups
[mono-project.git] / mcs / class / System.Private.CoreLib / System.Reflection / RuntimePropertyInfo.cs
blob1e5acdb163704472562f00f778daafc2d0a7e658
1 #nullable disable
2 using System.Collections.Generic;
3 using System.Globalization;
4 using System.Runtime.CompilerServices;
5 using System.Runtime.InteropServices;
6 using System.Text;
7 using Mono;
9 namespace System.Reflection
11 internal struct MonoPropertyInfo {
12 public Type parent;
13 public Type declaring_type;
14 public String name;
15 public MethodInfo get_method;
16 public MethodInfo set_method;
17 public PropertyAttributes attrs;
20 [Flags]
21 internal enum PInfo {
22 Attributes = 1,
23 GetMethod = 1 << 1,
24 SetMethod = 1 << 2,
25 ReflectedType = 1 << 3,
26 DeclaringType = 1 << 4,
27 Name = 1 << 5
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;
39 internal IntPtr prop;
40 MonoPropertyInfo info;
41 PInfo cached;
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,
47 PInfo req_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 {
57 get {
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;
70 if (isInherited) {
71 // We arrange things so the DeclaredOnly flag means "include inherited members"
72 bindingFlags |= BindingFlags.DeclaredOnly;
73 if (isStatic)
74 bindingFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
75 else
76 bindingFlags |= BindingFlags.Instance;
78 else {
79 if (isStatic)
80 bindingFlags |= BindingFlags.Static;
81 else
82 bindingFlags |= BindingFlags.Instance;
84 return bindingFlags;
87 public override Module Module {
88 get {
89 return GetRuntimeModule ();
93 internal RuntimeType GetDeclaringTypeInternal ()
95 return (RuntimeType) DeclaringType;
98 RuntimeType ReflectedTypeInternal {
99 get {
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));
119 sbName.Append(" ");
120 sbName.Append(Name);
122 var pi = GetIndexParameters ();
123 if (pi.Length > 0) {
124 sbName.Append (" [");
125 RuntimeParameterInfo.FormatParameters (sbName, pi, 0, serialization);
126 sbName.Append ("]");
129 return sbName.ToString();
131 #endregion
133 void CachePropertyInfo (PInfo flags)
135 if ((cached & flags) != flags) {
136 get_property_info (this, ref info, flags);
137 cached |= flags;
141 public override PropertyAttributes Attributes {
142 get {
143 CachePropertyInfo (PInfo.Attributes);
144 return info.attrs;
148 public override bool CanRead {
149 get {
150 CachePropertyInfo (PInfo.GetMethod);
151 return (info.get_method != null);
155 public override bool CanWrite {
156 get {
157 CachePropertyInfo (PInfo.SetMethod);
158 return (info.set_method != null);
162 public override Type PropertyType {
163 get {
164 CachePropertyInfo (PInfo.GetMethod | PInfo.SetMethod);
166 if (info.get_method != null) {
167 return info.get_method.ReturnType;
168 } else {
169 ParameterInfo[] parameters = info.set_method.GetParametersInternal ();
171 return parameters [parameters.Length - 1].ParameterType;
176 public override Type ReflectedType {
177 get {
178 CachePropertyInfo (PInfo.ReflectedType);
179 return info.parent;
183 public override Type DeclaringType {
184 get {
185 CachePropertyInfo (PInfo.DeclaringType);
186 return info.declaring_type;
190 public override string Name {
191 get {
192 CachePropertyInfo (PInfo.Name);
193 return info.name;
197 public override MethodInfo[] GetAccessors (bool nonPublic)
199 int nget = 0;
200 int nset = 0;
202 CachePropertyInfo (PInfo.GetMethod | PInfo.SetMethod);
204 if (info.set_method != null && (nonPublic || info.set_method.IsPublic))
205 nset = 1;
206 if (info.get_method != null && (nonPublic || info.get_method.IsPublic))
207 nget = 1;
209 MethodInfo[] res = new MethodInfo [nget + nset];
210 int n = 0;
211 if (nset != 0)
212 res [n++] = info.set_method;
213 if (nget != 0)
214 res [n++] = info.get_method;
215 return res;
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;
223 else
224 return null;
227 public override ParameterInfo[] GetIndexParameters ()
229 CachePropertyInfo (PInfo.GetMethod | PInfo.SetMethod);
230 ParameterInfo[] src;
231 int length;
232 if (info.get_method != null) {
233 src = info.get_method.GetParametersInternal ();
234 length = src.Length;
235 } else if (info.set_method != null) {
236 src = info.set_method.GetParametersInternal ();
237 length = src.Length - 1;
238 } else
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);
245 return dest;
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;
253 else
254 return null;
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)
300 return getter ();
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)
310 Type[] typeVector;
311 Type getterType;
312 object getterDelegate;
313 MethodInfo adapterFrame;
314 Type getterDelegateType;
315 string frameName;
317 if (method.IsStatic) {
318 typeVector = new Type[] { method.ReturnType };
319 getterDelegateType = typeof (StaticGetter<>);
320 frameName = "StaticGetterAdapterFrame";
321 } else {
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);
341 if (method == null)
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
346 try {
347 return cached_getter (obj);
348 } catch (Exception ex) {
349 throw new TargetInvocationException (ex);
352 } else {
353 try {
354 return cached_getter (obj);
355 } catch (Exception ex) {
356 throw new TargetInvocationException (ex);
359 #endif
362 return GetValue (obj, BindingFlags.Default, null, index, null);
365 public override object GetValue (object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
367 object ret = null;
369 MethodInfo method = GetGetMethod (true);
370 if (method == null)
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);
375 else
376 ret = method.Invoke (obj, invokeAttr, binder, index, culture);
378 return ret;
381 public override void SetValue (object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
383 MethodInfo method = GetSetMethod (true);
384 if (method == null)
385 throw new ArgumentException ("Set Method not found for '" + Name + "'");
387 object [] parms;
388 if (index == null || index.Length == 0)
389 parms = new object [] {value};
390 else {
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 {
413 get {
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);
429 if (pi == null)
430 throw new ArgumentException ("The property handle and the type handle are incompatible.");
431 return pi;