summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/Reflection
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/Reflection')
-rw-r--r--src/SMAPI/Framework/Reflection/InterfaceProxyBuilder.cs138
-rw-r--r--src/SMAPI/Framework/Reflection/ReflectedField.cs (renamed from src/SMAPI/Framework/Reflection/PrivateField.cs)16
-rw-r--r--src/SMAPI/Framework/Reflection/ReflectedMethod.cs (renamed from src/SMAPI/Framework/Reflection/PrivateMethod.cs)16
-rw-r--r--src/SMAPI/Framework/Reflection/ReflectedProperty.cs (renamed from src/SMAPI/Framework/Reflection/PrivateProperty.cs)42
-rw-r--r--src/SMAPI/Framework/Reflection/Reflector.cs106
5 files changed, 232 insertions, 86 deletions
diff --git a/src/SMAPI/Framework/Reflection/InterfaceProxyBuilder.cs b/src/SMAPI/Framework/Reflection/InterfaceProxyBuilder.cs
new file mode 100644
index 00000000..5abebc18
--- /dev/null
+++ b/src/SMAPI/Framework/Reflection/InterfaceProxyBuilder.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace StardewModdingAPI.Framework.Reflection
+{
+ /// <summary>Generates proxy classes to access mod APIs through an arbitrary interface.</summary>
+ internal class InterfaceProxyBuilder
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>The CLR module in which to create proxy classes.</summary>
+ private readonly ModuleBuilder ModuleBuilder;
+
+ /// <summary>The generated proxy types.</summary>
+ private readonly IDictionary<string, Type> GeneratedTypes = new Dictionary<string, Type>();
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ public InterfaceProxyBuilder()
+ {
+ AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName($"StardewModdingAPI.Proxies, Version={this.GetType().Assembly.GetName().Version}, Culture=neutral"), AssemblyBuilderAccess.Run);
+ this.ModuleBuilder = assemblyBuilder.DefineDynamicModule("StardewModdingAPI.Proxies");
+ }
+
+ /// <summary>Create an API proxy.</summary>
+ /// <typeparam name="TInterface">The interface through which to access the API.</typeparam>
+ /// <param name="instance">The API instance to access.</param>
+ /// <param name="sourceModID">The unique ID of the mod consuming the API.</param>
+ /// <param name="targetModID">The unique ID of the mod providing the API.</param>
+ public TInterface CreateProxy<TInterface>(object instance, string sourceModID, string targetModID)
+ where TInterface : class
+ {
+ // validate
+ if (instance == null)
+ throw new InvalidOperationException("Can't proxy access to a null API.");
+ if (!typeof(TInterface).IsInterface)
+ throw new InvalidOperationException("The proxy type must be an interface, not a class.");
+
+ // get proxy type
+ Type targetType = instance.GetType();
+ string proxyTypeName = $"StardewModdingAPI.Proxies.From<{sourceModID}_{typeof(TInterface).FullName}>_To<{targetModID}_{targetType.FullName}>";
+ if (!this.GeneratedTypes.TryGetValue(proxyTypeName, out Type type))
+ {
+ type = this.CreateProxyType(proxyTypeName, typeof(TInterface), targetType);
+ this.GeneratedTypes[proxyTypeName] = type;
+ }
+
+ // create instance
+ ConstructorInfo constructor = type.GetConstructor(new[] { targetType });
+ if (constructor == null)
+ throw new InvalidOperationException($"Couldn't find the constructor for generated proxy type '{proxyTypeName}'."); // should never happen
+ return (TInterface)constructor.Invoke(new[] { instance });
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Define a class which proxies access to a target type through an interface.</summary>
+ /// <param name="proxyTypeName">The name of the proxy type to generate.</param>
+ /// <param name="interfaceType">The interface type through which to access the target.</param>
+ /// <param name="targetType">The target type to access.</param>
+ private Type CreateProxyType(string proxyTypeName, Type interfaceType, Type targetType)
+ {
+ // define proxy type
+ TypeBuilder proxyBuilder = this.ModuleBuilder.DefineType(proxyTypeName, TypeAttributes.Public | TypeAttributes.Class);
+ proxyBuilder.AddInterfaceImplementation(interfaceType);
+
+ // create field to store target instance
+ FieldBuilder field = proxyBuilder.DefineField("__Target", targetType, FieldAttributes.Private);
+
+ // create constructor which accepts target instance
+ {
+ ConstructorBuilder constructor = proxyBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, new[] { targetType });
+ ILGenerator il = constructor.GetILGenerator();
+
+ il.Emit(OpCodes.Ldarg_0); // this
+ // ReSharper disable once AssignNullToNotNullAttribute -- never null
+ il.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0])); // call base constructor
+ il.Emit(OpCodes.Ldarg_0); // this
+ il.Emit(OpCodes.Ldarg_1); // load argument
+ il.Emit(OpCodes.Stfld, field); // set field to loaded argument
+ il.Emit(OpCodes.Ret);
+ }
+
+ // proxy methods
+ foreach (MethodInfo proxyMethod in interfaceType.GetMethods())
+ {
+ var targetMethod = targetType.GetMethod(proxyMethod.Name, proxyMethod.GetParameters().Select(a => a.ParameterType).ToArray());
+ if (targetMethod == null)
+ throw new InvalidOperationException($"The {interfaceType.FullName} interface defines method {proxyMethod.Name} which doesn't exist in the API.");
+
+ this.ProxyMethod(proxyBuilder, targetMethod, field);
+ }
+
+ // create type
+ return proxyBuilder.CreateType();
+ }
+
+ /// <summary>Define a method which proxies access to a method on the target.</summary>
+ /// <param name="proxyBuilder">The proxy type being generated.</param>
+ /// <param name="target">The target method.</param>
+ /// <param name="instanceField">The proxy field containing the API instance.</param>
+ private void ProxyMethod(TypeBuilder proxyBuilder, MethodInfo target, FieldBuilder instanceField)
+ {
+ Type[] argTypes = target.GetParameters().Select(a => a.ParameterType).ToArray();
+
+ // create method
+ MethodBuilder methodBuilder = proxyBuilder.DefineMethod(target.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual);
+ methodBuilder.SetParameters(argTypes);
+ methodBuilder.SetReturnType(target.ReturnType);
+
+ // create method body
+ {
+ ILGenerator il = methodBuilder.GetILGenerator();
+
+ // load target instance
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Ldfld, instanceField);
+
+ // invoke target method on instance
+ for (int i = 0; i < argTypes.Length; i++)
+ il.Emit(OpCodes.Ldarg, i + 1);
+ il.Emit(OpCodes.Call, target);
+
+ // return result
+ il.Emit(OpCodes.Ret);
+ }
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Reflection/PrivateField.cs b/src/SMAPI/Framework/Reflection/ReflectedField.cs
index 0bf45969..ad1557bb 100644
--- a/src/SMAPI/Framework/Reflection/PrivateField.cs
+++ b/src/SMAPI/Framework/Reflection/ReflectedField.cs
@@ -1,11 +1,11 @@
-using System;
+using System;
using System.Reflection;
namespace StardewModdingAPI.Framework.Reflection
{
- /// <summary>A private field obtained through reflection.</summary>
+ /// <summary>A field obtained through reflection.</summary>
/// <typeparam name="TValue">The field value type.</typeparam>
- internal class PrivateField<TValue> : IPrivateField<TValue>
+ internal class ReflectedField<TValue> : IPrivateField<TValue>, IReflectedField<TValue>
{
/*********
** Properties
@@ -37,7 +37,7 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="isStatic">Whether the field is static.</param>
/// <exception cref="ArgumentNullException">The <paramref name="parentType"/> or <paramref name="field"/> is null.</exception>
/// <exception cref="ArgumentException">The <paramref name="obj"/> is null for a non-static field, or not null for a static field.</exception>
- public PrivateField(Type parentType, object obj, FieldInfo field, bool isStatic)
+ public ReflectedField(Type parentType, object obj, FieldInfo field, bool isStatic)
{
// validate
if (parentType == null)
@@ -64,11 +64,11 @@ namespace StardewModdingAPI.Framework.Reflection
}
catch (InvalidCastException)
{
- throw new InvalidCastException($"Can't convert the private {this.DisplayName} field from {this.FieldInfo.FieldType.FullName} to {typeof(TValue).FullName}.");
+ throw new InvalidCastException($"Can't convert the {this.DisplayName} field from {this.FieldInfo.FieldType.FullName} to {typeof(TValue).FullName}.");
}
catch (Exception ex)
{
- throw new Exception($"Couldn't get the value of the private {this.DisplayName} field", ex);
+ throw new Exception($"Couldn't get the value of the {this.DisplayName} field", ex);
}
}
@@ -82,11 +82,11 @@ namespace StardewModdingAPI.Framework.Reflection
}
catch (InvalidCastException)
{
- throw new InvalidCastException($"Can't assign the private {this.DisplayName} field a {typeof(TValue).FullName} value, must be compatible with {this.FieldInfo.FieldType.FullName}.");
+ throw new InvalidCastException($"Can't assign the {this.DisplayName} field a {typeof(TValue).FullName} value, must be compatible with {this.FieldInfo.FieldType.FullName}.");
}
catch (Exception ex)
{
- throw new Exception($"Couldn't set the value of the private {this.DisplayName} field", ex);
+ throw new Exception($"Couldn't set the value of the {this.DisplayName} field", ex);
}
}
}
diff --git a/src/SMAPI/Framework/Reflection/PrivateMethod.cs b/src/SMAPI/Framework/Reflection/ReflectedMethod.cs
index ba2374f4..376de869 100644
--- a/src/SMAPI/Framework/Reflection/PrivateMethod.cs
+++ b/src/SMAPI/Framework/Reflection/ReflectedMethod.cs
@@ -3,8 +3,8 @@ using System.Reflection;
namespace StardewModdingAPI.Framework.Reflection
{
- /// <summary>A private method obtained through reflection.</summary>
- internal class PrivateMethod : IPrivateMethod
+ /// <summary>A method obtained through reflection.</summary>
+ internal class ReflectedMethod : IPrivateMethod, IReflectedMethod
{
/*********
** Properties
@@ -33,10 +33,10 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="parentType">The type that has the method.</param>
/// <param name="obj">The object that has the instance method(if applicable).</param>
/// <param name="method">The reflection metadata.</param>
- /// <param name="isStatic">Whether the field is static.</param>
+ /// <param name="isStatic">Whether the method is static.</param>
/// <exception cref="ArgumentNullException">The <paramref name="parentType"/> or <paramref name="method"/> is null.</exception>
/// <exception cref="ArgumentException">The <paramref name="obj"/> is null for a non-static method, or not null for a static method.</exception>
- public PrivateMethod(Type parentType, object obj, MethodInfo method, bool isStatic)
+ public ReflectedMethod(Type parentType, object obj, MethodInfo method, bool isStatic)
{
// validate
if (parentType == null)
@@ -67,7 +67,7 @@ namespace StardewModdingAPI.Framework.Reflection
}
catch (Exception ex)
{
- throw new Exception($"Couldn't invoke the private {this.DisplayName} field", ex);
+ throw new Exception($"Couldn't invoke the {this.DisplayName} method", ex);
}
// cast return value
@@ -77,7 +77,7 @@ namespace StardewModdingAPI.Framework.Reflection
}
catch (InvalidCastException)
{
- throw new InvalidCastException($"Can't convert the return value of the private {this.DisplayName} method from {this.MethodInfo.ReturnType.FullName} to {typeof(TValue).FullName}.");
+ throw new InvalidCastException($"Can't convert the return value of the {this.DisplayName} method from {this.MethodInfo.ReturnType.FullName} to {typeof(TValue).FullName}.");
}
}
@@ -92,8 +92,8 @@ namespace StardewModdingAPI.Framework.Reflection
}
catch (Exception ex)
{
- throw new Exception($"Couldn't invoke the private {this.DisplayName} field", ex);
+ throw new Exception($"Couldn't invoke the {this.DisplayName} method", ex);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/SMAPI/Framework/Reflection/PrivateProperty.cs b/src/SMAPI/Framework/Reflection/ReflectedProperty.cs
index be346d71..d6c964c1 100644
--- a/src/SMAPI/Framework/Reflection/PrivateProperty.cs
+++ b/src/SMAPI/Framework/Reflection/ReflectedProperty.cs
@@ -3,9 +3,9 @@ using System.Reflection;
namespace StardewModdingAPI.Framework.Reflection
{
- /// <summary>A private property obtained through reflection.</summary>
+ /// <summary>A property obtained through reflection.</summary>
/// <typeparam name="TValue">The property value type.</typeparam>
- internal class PrivateProperty<TValue> : IPrivateProperty<TValue>
+ internal class ReflectedProperty<TValue> : IPrivateProperty<TValue>, IReflectedProperty<TValue>
{
/*********
** Properties
@@ -14,10 +14,10 @@ namespace StardewModdingAPI.Framework.Reflection
private readonly string DisplayName;
/// <summary>The underlying property getter.</summary>
- private readonly Func<TValue> GetterDelegate;
+ private readonly Func<TValue> GetMethod;
/// <summary>The underlying property setter.</summary>
- private readonly Action<TValue> SetterDelegate;
+ private readonly Action<TValue> SetMethod;
/*********
@@ -31,13 +31,13 @@ namespace StardewModdingAPI.Framework.Reflection
** Public methods
*********/
/// <summary>Construct an instance.</summary>
- /// <param name="parentType">The type that has the field.</param>
- /// <param name="obj">The object that has the instance field (if applicable).</param>
+ /// <param name="parentType">The type that has the property.</param>
+ /// <param name="obj">The object that has the instance property (if applicable).</param>
/// <param name="property">The reflection metadata.</param>
- /// <param name="isStatic">Whether the field is static.</param>
+ /// <param name="isStatic">Whether the property is static.</param>
/// <exception cref="ArgumentNullException">The <paramref name="parentType"/> or <paramref name="property"/> is null.</exception>
- /// <exception cref="ArgumentException">The <paramref name="obj"/> is null for a non-static field, or not null for a static field.</exception>
- public PrivateProperty(Type parentType, object obj, PropertyInfo property, bool isStatic)
+ /// <exception cref="ArgumentException">The <paramref name="obj"/> is null for a non-static property, or not null for a static property.</exception>
+ public ReflectedProperty(Type parentType, object obj, PropertyInfo property, bool isStatic)
{
// validate input
if (parentType == null)
@@ -55,24 +55,29 @@ namespace StardewModdingAPI.Framework.Reflection
this.DisplayName = $"{parentType.FullName}::{property.Name}";
this.PropertyInfo = property;
- this.GetterDelegate = (Func<TValue>)Delegate.CreateDelegate(typeof(Func<TValue>), obj, this.PropertyInfo.GetMethod);
- this.SetterDelegate = (Action<TValue>)Delegate.CreateDelegate(typeof(Action<TValue>), obj, this.PropertyInfo.SetMethod);
+ if (this.PropertyInfo.GetMethod != null)
+ this.GetMethod = (Func<TValue>)Delegate.CreateDelegate(typeof(Func<TValue>), obj, this.PropertyInfo.GetMethod);
+ if (this.PropertyInfo.SetMethod != null)
+ this.SetMethod = (Action<TValue>)Delegate.CreateDelegate(typeof(Action<TValue>), obj, this.PropertyInfo.SetMethod);
}
/// <summary>Get the property value.</summary>
public TValue GetValue()
{
+ if (this.GetMethod == null)
+ throw new InvalidOperationException($"The {this.DisplayName} property has no get method.");
+
try
{
- return this.GetterDelegate();
+ return this.GetMethod();
}
catch (InvalidCastException)
{
- throw new InvalidCastException($"Can't convert the private {this.DisplayName} property from {this.PropertyInfo.PropertyType.FullName} to {typeof(TValue).FullName}.");
+ throw new InvalidCastException($"Can't convert the {this.DisplayName} property from {this.PropertyInfo.PropertyType.FullName} to {typeof(TValue).FullName}.");
}
catch (Exception ex)
{
- throw new Exception($"Couldn't get the value of the private {this.DisplayName} property", ex);
+ throw new Exception($"Couldn't get the value of the {this.DisplayName} property", ex);
}
}
@@ -80,17 +85,20 @@ namespace StardewModdingAPI.Framework.Reflection
//// <param name="value">The value to set.</param>
public void SetValue(TValue value)
{
+ if (this.SetMethod == null)
+ throw new InvalidOperationException($"The {this.DisplayName} property has no set method.");
+
try
{
- this.SetterDelegate(value);
+ this.SetMethod(value);
}
catch (InvalidCastException)
{
- throw new InvalidCastException($"Can't assign the private {this.DisplayName} property a {typeof(TValue).FullName} value, must be compatible with {this.PropertyInfo.PropertyType.FullName}.");
+ throw new InvalidCastException($"Can't assign the {this.DisplayName} property a {typeof(TValue).FullName} value, must be compatible with {this.PropertyInfo.PropertyType.FullName}.");
}
catch (Exception ex)
{
- throw new Exception($"Couldn't set the value of the private {this.DisplayName} property", ex);
+ throw new Exception($"Couldn't set the value of the {this.DisplayName} property", ex);
}
}
}
diff --git a/src/SMAPI/Framework/Reflection/Reflector.cs b/src/SMAPI/Framework/Reflection/Reflector.cs
index 23a48505..910e3a54 100644
--- a/src/SMAPI/Framework/Reflection/Reflector.cs
+++ b/src/SMAPI/Framework/Reflection/Reflector.cs
@@ -5,7 +5,7 @@ using System.Runtime.Caching;
namespace StardewModdingAPI.Framework.Reflection
{
- /// <summary>Provides helper methods for accessing private game code.</summary>
+ /// <summary>Provides helper methods for accessing inaccessible code.</summary>
/// <remarks>This implementation searches up the type hierarchy, and caches the reflected fields and methods with a sliding expiry (to optimise performance without unnecessary memory usage).</remarks>
internal class Reflector
{
@@ -25,139 +25,139 @@ namespace StardewModdingAPI.Framework.Reflection
/****
** Fields
****/
- /// <summary>Get a private instance field.</summary>
+ /// <summary>Get a instance field.</summary>
/// <typeparam name="TValue">The field type.</typeparam>
/// <param name="obj">The object which has the field.</param>
/// <param name="name">The field name.</param>
- /// <param name="required">Whether to throw an exception if the private field is not found.</param>
+ /// <param name="required">Whether to throw an exception if the field is not found.</param>
/// <returns>Returns the field wrapper, or <c>null</c> if the field doesn't exist and <paramref name="required"/> is <c>false</c>.</returns>
- public IPrivateField<TValue> GetPrivateField<TValue>(object obj, string name, bool required = true)
+ public IReflectedField<TValue> GetField<TValue>(object obj, string name, bool required = true)
{
// validate
if (obj == null)
- throw new ArgumentNullException(nameof(obj), "Can't get a private instance field from a null object.");
+ throw new ArgumentNullException(nameof(obj), "Can't get a instance field from a null object.");
// get field from hierarchy
- IPrivateField<TValue> field = this.GetFieldFromHierarchy<TValue>(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+ IReflectedField<TValue> field = this.GetFieldFromHierarchy<TValue>(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (required && field == null)
- throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a private '{name}' instance field.");
+ throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a '{name}' instance field.");
return field;
}
- /// <summary>Get a private static field.</summary>
+ /// <summary>Get a static field.</summary>
/// <typeparam name="TValue">The field type.</typeparam>
/// <param name="type">The type which has the field.</param>
/// <param name="name">The field name.</param>
- /// <param name="required">Whether to throw an exception if the private field is not found.</param>
- public IPrivateField<TValue> GetPrivateField<TValue>(Type type, string name, bool required = true)
+ /// <param name="required">Whether to throw an exception if the field is not found.</param>
+ public IReflectedField<TValue> GetField<TValue>(Type type, string name, bool required = true)
{
// get field from hierarchy
- IPrivateField<TValue> field = this.GetFieldFromHierarchy<TValue>(type, null, name, BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public);
+ IReflectedField<TValue> field = this.GetFieldFromHierarchy<TValue>(type, null, name, BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public);
if (required && field == null)
- throw new InvalidOperationException($"The {type.FullName} object doesn't have a private '{name}' static field.");
+ throw new InvalidOperationException($"The {type.FullName} object doesn't have a '{name}' static field.");
return field;
}
/****
** Properties
****/
- /// <summary>Get a private instance property.</summary>
+ /// <summary>Get a 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)
+ /// <param name="required">Whether to throw an exception if the property is not found.</param>
+ public IReflectedProperty<TValue> GetProperty<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.");
+ throw new ArgumentNullException(nameof(obj), "Can't get a instance property from a null object.");
// get property from hierarchy
- IPrivateProperty<TValue> property = this.GetPropertyFromHierarchy<TValue>(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+ IReflectedProperty<TValue> property = this.GetPropertyFromHierarchy<TValue>(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (required && property == null)
- throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a private '{name}' instance property.");
+ throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a '{name}' instance property.");
return property;
}
- /// <summary>Get a private static property.</summary>
+ /// <summary>Get a 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)
+ /// <param name="required">Whether to throw an exception if the property is not found.</param>
+ public IReflectedProperty<TValue> GetProperty<TValue>(Type type, string name, bool required = true)
{
// get field from hierarchy
- IPrivateProperty<TValue> property = this.GetPropertyFromHierarchy<TValue>(type, null, name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
+ IReflectedProperty<TValue> property = this.GetPropertyFromHierarchy<TValue>(type, null, name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
if (required && property == null)
- throw new InvalidOperationException($"The {type.FullName} object doesn't have a private '{name}' static property.");
+ throw new InvalidOperationException($"The {type.FullName} object doesn't have a '{name}' static property.");
return property;
}
/****
** Methods
****/
- /// <summary>Get a private instance method.</summary>
+ /// <summary>Get a instance method.</summary>
/// <param name="obj">The object which has the method.</param>
/// <param name="name">The field name.</param>
- /// <param name="required">Whether to throw an exception if the private field is not found.</param>
- public IPrivateMethod GetPrivateMethod(object obj, string name, bool required = true)
+ /// <param name="required">Whether to throw an exception if the field is not found.</param>
+ public IReflectedMethod GetMethod(object obj, string name, bool required = true)
{
// validate
if (obj == null)
- throw new ArgumentNullException(nameof(obj), "Can't get a private instance method from a null object.");
+ throw new ArgumentNullException(nameof(obj), "Can't get a instance method from a null object.");
// get method from hierarchy
- IPrivateMethod method = this.GetMethodFromHierarchy(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+ IReflectedMethod method = this.GetMethodFromHierarchy(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (required && method == null)
- throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a private '{name}' instance method.");
+ throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a '{name}' instance method.");
return method;
}
- /// <summary>Get a private static method.</summary>
+ /// <summary>Get a static method.</summary>
/// <param name="type">The type which has the method.</param>
/// <param name="name">The field name.</param>
- /// <param name="required">Whether to throw an exception if the private field is not found.</param>
- public IPrivateMethod GetPrivateMethod(Type type, string name, bool required = true)
+ /// <param name="required">Whether to throw an exception if the field is not found.</param>
+ public IReflectedMethod GetMethod(Type type, string name, bool required = true)
{
// get method from hierarchy
- IPrivateMethod method = this.GetMethodFromHierarchy(type, null, name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
+ IReflectedMethod method = this.GetMethodFromHierarchy(type, null, name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
if (required && method == null)
- throw new InvalidOperationException($"The {type.FullName} object doesn't have a private '{name}' static method.");
+ throw new InvalidOperationException($"The {type.FullName} object doesn't have a '{name}' static method.");
return method;
}
/****
** Methods by signature
****/
- /// <summary>Get a private instance method.</summary>
+ /// <summary>Get a instance method.</summary>
/// <param name="obj">The object which has the method.</param>
/// <param name="name">The field name.</param>
/// <param name="argumentTypes">The argument types of the method signature to find.</param>
- /// <param name="required">Whether to throw an exception if the private field is not found.</param>
- public IPrivateMethod GetPrivateMethod(object obj, string name, Type[] argumentTypes, bool required = true)
+ /// <param name="required">Whether to throw an exception if the field is not found.</param>
+ public IReflectedMethod GetMethod(object obj, string name, Type[] argumentTypes, bool required = true)
{
// validate parent
if (obj == null)
- throw new ArgumentNullException(nameof(obj), "Can't get a private instance method from a null object.");
+ throw new ArgumentNullException(nameof(obj), "Can't get a instance method from a null object.");
// get method from hierarchy
- PrivateMethod method = this.GetMethodFromHierarchy(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, argumentTypes);
+ ReflectedMethod method = this.GetMethodFromHierarchy(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, argumentTypes);
if (required && method == null)
- throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a private '{name}' instance method with that signature.");
+ throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a '{name}' instance method with that signature.");
return method;
}
- /// <summary>Get a private static method.</summary>
+ /// <summary>Get a static method.</summary>
/// <param name="type">The type which has the method.</param>
/// <param name="name">The field name.</param>
/// <param name="argumentTypes">The argument types of the method signature to find.</param>
- /// <param name="required">Whether to throw an exception if the private field is not found.</param>
- public IPrivateMethod GetPrivateMethod(Type type, string name, Type[] argumentTypes, bool required = true)
+ /// <param name="required">Whether to throw an exception if the field is not found.</param>
+ public IReflectedMethod GetMethod(Type type, string name, Type[] argumentTypes, bool required = true)
{
// get field from hierarchy
- PrivateMethod method = this.GetMethodFromHierarchy(type, null, name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, argumentTypes);
+ ReflectedMethod method = this.GetMethodFromHierarchy(type, null, name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, argumentTypes);
if (required && method == null)
- throw new InvalidOperationException($"The {type.FullName} object doesn't have a private '{name}' static method with that signature.");
+ throw new InvalidOperationException($"The {type.FullName} object doesn't have a '{name}' static method with that signature.");
return method;
}
@@ -171,7 +171,7 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="obj">The object which has the field.</param>
/// <param name="name">The field name.</param>
/// <param name="bindingFlags">The reflection binding which flags which indicates what type of field to find.</param>
- private IPrivateField<TValue> GetFieldFromHierarchy<TValue>(Type type, object obj, string name, BindingFlags bindingFlags)
+ private IReflectedField<TValue> GetFieldFromHierarchy<TValue>(Type type, object obj, string name, BindingFlags bindingFlags)
{
bool isStatic = bindingFlags.HasFlag(BindingFlags.Static);
FieldInfo field = this.GetCached<FieldInfo>($"field::{isStatic}::{type.FullName}::{name}", () =>
@@ -183,7 +183,7 @@ namespace StardewModdingAPI.Framework.Reflection
});
return field != null
- ? new PrivateField<TValue>(type, obj, field, isStatic)
+ ? new ReflectedField<TValue>(type, obj, field, isStatic)
: null;
}
@@ -193,7 +193,7 @@ namespace StardewModdingAPI.Framework.Reflection
/// <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)
+ private IReflectedProperty<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}", () =>
@@ -205,7 +205,7 @@ namespace StardewModdingAPI.Framework.Reflection
});
return property != null
- ? new PrivateProperty<TValue>(type, obj, property, isStatic)
+ ? new ReflectedProperty<TValue>(type, obj, property, isStatic)
: null;
}
@@ -214,7 +214,7 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="obj">The object which has the method.</param>
/// <param name="name">The method name.</param>
/// <param name="bindingFlags">The reflection binding which flags which indicates what type of method to find.</param>
- private IPrivateMethod GetMethodFromHierarchy(Type type, object obj, string name, BindingFlags bindingFlags)
+ private IReflectedMethod GetMethodFromHierarchy(Type type, object obj, string name, BindingFlags bindingFlags)
{
bool isStatic = bindingFlags.HasFlag(BindingFlags.Static);
MethodInfo method = this.GetCached($"method::{isStatic}::{type.FullName}::{name}", () =>
@@ -226,7 +226,7 @@ namespace StardewModdingAPI.Framework.Reflection
});
return method != null
- ? new PrivateMethod(type, obj, method, isStatic: bindingFlags.HasFlag(BindingFlags.Static))
+ ? new ReflectedMethod(type, obj, method, isStatic: bindingFlags.HasFlag(BindingFlags.Static))
: null;
}
@@ -236,7 +236,7 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="name">The method name.</param>
/// <param name="bindingFlags">The reflection binding which flags which indicates what type of method to find.</param>
/// <param name="argumentTypes">The argument types of the method signature to find.</param>
- private PrivateMethod GetMethodFromHierarchy(Type type, object obj, string name, BindingFlags bindingFlags, Type[] argumentTypes)
+ private ReflectedMethod GetMethodFromHierarchy(Type type, object obj, string name, BindingFlags bindingFlags, Type[] argumentTypes)
{
bool isStatic = bindingFlags.HasFlag(BindingFlags.Static);
MethodInfo method = this.GetCached($"method::{isStatic}::{type.FullName}::{name}({string.Join(",", argumentTypes.Select(p => p.FullName))})", () =>
@@ -247,7 +247,7 @@ namespace StardewModdingAPI.Framework.Reflection
return methodInfo;
});
return method != null
- ? new PrivateMethod(type, obj, method, isStatic)
+ ? new ReflectedMethod(type, obj, method, isStatic)
: null;
}