summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-04-05 14:55:46 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-04-05 14:55:46 -0400
commitdbb9bd84306830456032778fc11fb9a34dd140c7 (patch)
tree0219cab065bfffbbbb9b048b6a30044f510be2c5 /src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
parent9c9833c9086b758589dafee10243e3bf47e12d73 (diff)
parent4675da0600edf6781cd740549ad0a175b606fc1e (diff)
downloadSMAPI-dbb9bd84306830456032778fc11fb9a34dd140c7.tar.gz
SMAPI-dbb9bd84306830456032778fc11fb9a34dd140c7.tar.bz2
SMAPI-dbb9bd84306830456032778fc11fb9a34dd140c7.zip
Merge branch 'develop-1.9' into stable
Diffstat (limited to 'src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs')
-rw-r--r--src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs b/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
index edf59b81..7a5789dc 100644
--- a/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
+++ b/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
@@ -59,6 +59,41 @@ namespace StardewModdingAPI.Framework.Reflection
}
/****
+ ** Properties
+ ****/
+ /// <summary>Get a private instance property.</summary>
+ /// <typeparam name="TValue">The property type.</typeparam>
+ /// <param name="obj">The object which has the property.</param>
+ /// <param name="name">The property name.</param>
+ /// <param name="required">Whether to throw an exception if the private property is not found.</param>
+ public IPrivateProperty<TValue> GetPrivateProperty<TValue>(object obj, string name, bool required = true)
+ {
+ // validate
+ if (obj == null)
+ throw new ArgumentNullException(nameof(obj), "Can't get a private instance property from a null object.");
+
+ // get property from hierarchy
+ IPrivateProperty<TValue> property = this.GetPropertyFromHierarchy<TValue>(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic);
+ if (required && property == null)
+ throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a private '{name}' instance property.");
+ return property;
+ }
+
+ /// <summary>Get a private static property.</summary>
+ /// <typeparam name="TValue">The property type.</typeparam>
+ /// <param name="type">The type which has the property.</param>
+ /// <param name="name">The property name.</param>
+ /// <param name="required">Whether to throw an exception if the private property is not found.</param>
+ public IPrivateProperty<TValue> GetPrivateProperty<TValue>(Type type, string name, bool required = true)
+ {
+ // get field from hierarchy
+ IPrivateProperty<TValue> property = this.GetPropertyFromHierarchy<TValue>(type, null, name, BindingFlags.NonPublic | BindingFlags.Static);
+ if (required && property == null)
+ throw new InvalidOperationException($"The {type.FullName} object doesn't have a private '{name}' static property.");
+ return property;
+ }
+
+ /****
** Field values
** (shorthand since this is the most common case)
****/
@@ -192,6 +227,28 @@ namespace StardewModdingAPI.Framework.Reflection
: null;
}
+ /// <summary>Get a property from the type hierarchy.</summary>
+ /// <typeparam name="TValue">The expected property type.</typeparam>
+ /// <param name="type">The type which has the property.</param>
+ /// <param name="obj">The object which has the property.</param>
+ /// <param name="name">The property name.</param>
+ /// <param name="bindingFlags">The reflection binding which flags which indicates what type of property to find.</param>
+ private IPrivateProperty<TValue> GetPropertyFromHierarchy<TValue>(Type type, object obj, string name, BindingFlags bindingFlags)
+ {
+ bool isStatic = bindingFlags.HasFlag(BindingFlags.Static);
+ PropertyInfo property = this.GetCached<PropertyInfo>($"property::{isStatic}::{type.FullName}::{name}", () =>
+ {
+ PropertyInfo propertyInfo = null;
+ for (; type != null && propertyInfo == null; type = type.BaseType)
+ propertyInfo = type.GetProperty(name, bindingFlags);
+ return propertyInfo;
+ });
+
+ return property != null
+ ? new PrivateProperty<TValue>(type, obj, property, isStatic)
+ : null;
+ }
+
/// <summary>Get a method from the type hierarchy.</summary>
/// <param name="type">The type which has the method.</param>
/// <param name="obj">The object which has the method.</param>