adjust reflection API to correctly reflect what it does (#410)
This commit is contained in:
parent
80c4d93559
commit
8776d1afa6
|
@ -57,14 +57,14 @@ namespace StardewModdingAPI.Framework.Content
|
|||
public ContentCache(LocalizedContentManager contentManager, Reflector reflection, char[] possiblePathSeparators, string preferredPathSeparator)
|
||||
{
|
||||
// init
|
||||
this.Cache = reflection.GetPrivateField<Dictionary<string, object>>(contentManager, "loadedAssets").GetValue();
|
||||
this.Cache = reflection.GetField<Dictionary<string, object>>(contentManager, "loadedAssets").GetValue();
|
||||
this.PossiblePathSeparators = possiblePathSeparators;
|
||||
this.PreferredPathSeparator = preferredPathSeparator;
|
||||
|
||||
// get key normalisation logic
|
||||
if (Constants.TargetPlatform == Platform.Windows)
|
||||
{
|
||||
IPrivateMethod method = reflection.GetPrivateMethod(typeof(TitleContainer), "GetCleanPath");
|
||||
IReflectedMethod method = reflection.GetMethod(typeof(TitleContainer), "GetCleanPath");
|
||||
this.NormaliseAssetNameForPlatform = path => method.Invoke<string>(path);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace StardewModdingAPI.Framework
|
|||
return;
|
||||
|
||||
// build message
|
||||
string message = $"{source ?? "An unknown mod"} uses deprecated code ({nounPhrase}).";
|
||||
string message = $"{source ?? "An unknown mod"} uses deprecated code ({nounPhrase} is deprecated since SMAPI {version}).";
|
||||
if (source == null)
|
||||
message += $"{Environment.NewLine}{Environment.StackTrace}";
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace StardewModdingAPI.Framework
|
|||
#endif
|
||||
|
||||
// get result
|
||||
return reflection.GetPrivateField<bool>(Game1.spriteBatch, fieldName).GetValue();
|
||||
return reflection.GetField<bool>(Game1.spriteBatch, fieldName).GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <summary>The mod name for error messages.</summary>
|
||||
private readonly string ModName;
|
||||
|
||||
/// <summary>Manages deprecation warnings.</summary>
|
||||
private readonly DeprecationManager DeprecationManager;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -25,15 +28,88 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <param name="modID">The unique ID of the relevant mod.</param>
|
||||
/// <param name="modName">The mod name for error messages.</param>
|
||||
/// <param name="reflector">The underlying reflection helper.</param>
|
||||
public ReflectionHelper(string modID, string modName, Reflector reflector)
|
||||
/// <param name="deprecationManager">Manages deprecation warnings.</param>
|
||||
public ReflectionHelper(string modID, string modName, Reflector reflector, DeprecationManager deprecationManager)
|
||||
: base(modID)
|
||||
{
|
||||
this.ModName = modName;
|
||||
this.Reflector = reflector;
|
||||
this.DeprecationManager = deprecationManager;
|
||||
}
|
||||
|
||||
/// <summary>Get an 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 field is not found.</param>
|
||||
public IReflectedField<TValue> GetField<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetField<TValue>(obj, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
/// <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 field is not found.</param>
|
||||
public IReflectedField<TValue> GetField<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetField<TValue>(type, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Get an 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 property is not found.</param>
|
||||
public IReflectedProperty<TValue> GetProperty<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetProperty<TValue>(obj, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
/// <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 property is not found.</param>
|
||||
public IReflectedProperty<TValue> GetProperty<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetProperty<TValue>(type, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Get an 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 field is not found.</param>
|
||||
public IReflectedMethod GetMethod(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetMethod(obj, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
/// <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 field is not found.</param>
|
||||
public IReflectedMethod GetMethod(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetMethod(type, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/****
|
||||
** Fields
|
||||
** Obsolete
|
||||
****/
|
||||
/// <summary>Get a private instance field.</summary>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
|
@ -41,11 +117,11 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <param name="name">The field name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the private 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>
|
||||
[Obsolete]
|
||||
public IPrivateField<TValue> GetPrivateField<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateField<TValue>(obj, name, required)
|
||||
);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
return (IPrivateField<TValue>)this.GetField<TValue>(obj, name, required);
|
||||
}
|
||||
|
||||
/// <summary>Get a private static field.</summary>
|
||||
|
@ -53,26 +129,23 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <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>
|
||||
[Obsolete]
|
||||
public IPrivateField<TValue> GetPrivateField<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateField<TValue>(type, name, required)
|
||||
);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
return (IPrivateField<TValue>)this.GetField<TValue>(type, name, required);
|
||||
}
|
||||
|
||||
/****
|
||||
** 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>
|
||||
[Obsolete]
|
||||
public IPrivateProperty<TValue> GetPrivateProperty<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateProperty<TValue>(obj, name, required)
|
||||
);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
return (IPrivateProperty<TValue>)this.GetProperty<TValue>(obj, name, required);
|
||||
}
|
||||
|
||||
/// <summary>Get a private static property.</summary>
|
||||
|
@ -80,17 +153,13 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <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>
|
||||
[Obsolete]
|
||||
public IPrivateProperty<TValue> GetPrivateProperty<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateProperty<TValue>(type, name, required)
|
||||
);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
return (IPrivateProperty<TValue>)this.GetProperty<TValue>(type, name, required);
|
||||
}
|
||||
|
||||
/****
|
||||
** Field values
|
||||
** (shorthand since this is the most common case)
|
||||
****/
|
||||
/// <summary>Get the value of a private instance field.</summary>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
/// <param name="obj">The object which has the field.</param>
|
||||
|
@ -101,9 +170,11 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
|
||||
/// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(object,string,bool)" /> instead.
|
||||
/// </remarks>
|
||||
[Obsolete]
|
||||
public TValue GetPrivateValue<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
IPrivateField<TValue> field = this.GetPrivateField<TValue>(obj, name, required);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
IPrivateField<TValue> field = (IPrivateField<TValue>)this.GetField<TValue>(obj, name, required);
|
||||
return field != null
|
||||
? field.GetValue()
|
||||
: default(TValue);
|
||||
|
@ -119,64 +190,36 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
|
||||
/// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(Type,string,bool)" /> instead.
|
||||
/// </remarks>
|
||||
[Obsolete]
|
||||
public TValue GetPrivateValue<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
IPrivateField<TValue> field = this.GetPrivateField<TValue>(type, name, required);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
IPrivateField<TValue> field = (IPrivateField<TValue>)this.GetField<TValue>(type, name, required);
|
||||
return field != null
|
||||
? field.GetValue()
|
||||
: default(TValue);
|
||||
}
|
||||
|
||||
/****
|
||||
** Methods
|
||||
****/
|
||||
/// <summary>Get a private 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>
|
||||
[Obsolete]
|
||||
public IPrivateMethod GetPrivateMethod(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateMethod(obj, name, required)
|
||||
);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
return (IPrivateMethod)this.GetMethod(obj, name, required);
|
||||
}
|
||||
|
||||
/// <summary>Get a private 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>
|
||||
[Obsolete]
|
||||
public IPrivateMethod GetPrivateMethod(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateMethod(type, name, required)
|
||||
);
|
||||
}
|
||||
|
||||
/****
|
||||
** Methods by signature
|
||||
****/
|
||||
/// <summary>Get a private 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)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateMethod(obj, name, argumentTypes, required)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Get a private 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)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
this.Reflector.GetPrivateMethod(type, name, argumentTypes, required)
|
||||
);
|
||||
this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
|
||||
return (IPrivateMethod)this.GetMethod(type, name, required);
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,7 +230,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <typeparam name="T">The field value type.</typeparam>
|
||||
/// <param name="field">The field being accessed.</param>
|
||||
/// <returns>Returns the same field instance for convenience.</returns>
|
||||
private IPrivateField<T> AssertAccessAllowed<T>(IPrivateField<T> field)
|
||||
private IReflectedField<T> AssertAccessAllowed<T>(IReflectedField<T> field)
|
||||
{
|
||||
this.AssertAccessAllowed(field?.FieldInfo);
|
||||
return field;
|
||||
|
@ -197,7 +240,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <typeparam name="T">The property value type.</typeparam>
|
||||
/// <param name="property">The property being accessed.</param>
|
||||
/// <returns>Returns the same property instance for convenience.</returns>
|
||||
private IPrivateProperty<T> AssertAccessAllowed<T>(IPrivateProperty<T> property)
|
||||
private IReflectedProperty<T> AssertAccessAllowed<T>(IReflectedProperty<T> property)
|
||||
{
|
||||
this.AssertAccessAllowed(property?.PropertyInfo);
|
||||
return property;
|
||||
|
@ -206,7 +249,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <summary>Assert that mods can use the reflection helper to access the given member.</summary>
|
||||
/// <param name="method">The method being accessed.</param>
|
||||
/// <returns>Returns the same method instance for convenience.</returns>
|
||||
private IPrivateMethod AssertAccessAllowed(IPrivateMethod method)
|
||||
private IReflectedMethod AssertAccessAllowed(IReflectedMethod method)
|
||||
{
|
||||
this.AssertAccessAllowed(method?.MethodInfo);
|
||||
return method;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -65,7 +65,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
public TValue GetValue()
|
||||
{
|
||||
if (this.GetMethod == null)
|
||||
throw new InvalidOperationException($"The private {this.DisplayName} property has no get method.");
|
||||
throw new InvalidOperationException($"The {this.DisplayName} property has no get method.");
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -73,11 +73,11 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
public void SetValue(TValue value)
|
||||
{
|
||||
if (this.SetMethod == null)
|
||||
throw new InvalidOperationException($"The private {this.DisplayName} property has no set method.");
|
||||
throw new InvalidOperationException($"The {this.DisplayName} property has no set method.");
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -94,11 +94,11 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace StardewModdingAPI.Framework
|
|||
private readonly ContentCache Cache;
|
||||
|
||||
/// <summary>The private <see cref="LocalizedContentManager"/> method which generates the locale portion of an asset name.</summary>
|
||||
private readonly IPrivateMethod GetKeyLocale;
|
||||
private readonly IReflectedMethod GetKeyLocale;
|
||||
|
||||
/// <summary>The language codes used in asset keys.</summary>
|
||||
private readonly IDictionary<string, LanguageCode> KeyLocales;
|
||||
|
@ -101,7 +101,7 @@ namespace StardewModdingAPI.Framework
|
|||
// init
|
||||
this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor));
|
||||
this.Cache = new ContentCache(this, reflection, SContentManager.PossiblePathSeparators, SContentManager.PreferredPathSeparator);
|
||||
this.GetKeyLocale = reflection.GetPrivateMethod(this, "languageCode");
|
||||
this.GetKeyLocale = reflection.GetMethod(this, "languageCode");
|
||||
this.ModContentPrefix = this.GetAssetNameFromFilePath(Constants.ModPath);
|
||||
|
||||
// get asset data
|
||||
|
@ -413,7 +413,7 @@ namespace StardewModdingAPI.Framework
|
|||
private IDictionary<string, LanguageCode> GetKeyLocales(Reflector reflection)
|
||||
{
|
||||
// get the private code field directly to avoid changed-code logic
|
||||
IPrivateField<LanguageCode> codeField = reflection.GetPrivateField<LanguageCode>(typeof(LocalizedContentManager), "_currentLangCode");
|
||||
IReflectedField<LanguageCode> codeField = reflection.GetField<LanguageCode>(typeof(LocalizedContentManager), "_currentLangCode");
|
||||
|
||||
// remember previous settings
|
||||
LanguageCode previousCode = codeField.GetValue();
|
||||
|
|
|
@ -133,20 +133,20 @@ namespace StardewModdingAPI.Framework
|
|||
|
||||
// ReSharper disable ArrangeStaticMemberQualifier, ArrangeThisQualifier, InconsistentNaming
|
||||
/// <summary>Used to access private fields and methods.</summary>
|
||||
private static List<float> _fpsList => SGame.Reflection.GetPrivateField<List<float>>(typeof(Game1), nameof(_fpsList)).GetValue();
|
||||
private static Stopwatch _fpsStopwatch => SGame.Reflection.GetPrivateField<Stopwatch>(typeof(Game1), nameof(SGame._fpsStopwatch)).GetValue();
|
||||
private static List<float> _fpsList => SGame.Reflection.GetField<List<float>>(typeof(Game1), nameof(_fpsList)).GetValue();
|
||||
private static Stopwatch _fpsStopwatch => SGame.Reflection.GetField<Stopwatch>(typeof(Game1), nameof(SGame._fpsStopwatch)).GetValue();
|
||||
private static float _fps
|
||||
{
|
||||
set => SGame.Reflection.GetPrivateField<float>(typeof(Game1), nameof(_fps)).SetValue(value);
|
||||
set => SGame.Reflection.GetField<float>(typeof(Game1), nameof(_fps)).SetValue(value);
|
||||
}
|
||||
private static Task _newDayTask => SGame.Reflection.GetPrivateField<Task>(typeof(Game1), nameof(_newDayTask)).GetValue();
|
||||
private Color bgColor => SGame.Reflection.GetPrivateField<Color>(this, nameof(bgColor)).GetValue();
|
||||
public RenderTarget2D screenWrapper => SGame.Reflection.GetPrivateProperty<RenderTarget2D>(this, "screen").GetValue(); // deliberately renamed to avoid an infinite loop
|
||||
public BlendState lightingBlend => SGame.Reflection.GetPrivateField<BlendState>(this, nameof(lightingBlend)).GetValue();
|
||||
private readonly Action drawFarmBuildings = () => SGame.Reflection.GetPrivateMethod(SGame.Instance, nameof(drawFarmBuildings)).Invoke();
|
||||
private readonly Action drawHUD = () => SGame.Reflection.GetPrivateMethod(SGame.Instance, nameof(drawHUD)).Invoke();
|
||||
private readonly Action drawDialogueBox = () => SGame.Reflection.GetPrivateMethod(SGame.Instance, nameof(drawDialogueBox)).Invoke();
|
||||
private readonly Action renderScreenBuffer = () => SGame.Reflection.GetPrivateMethod(SGame.Instance, nameof(renderScreenBuffer)).Invoke();
|
||||
private static Task _newDayTask => SGame.Reflection.GetField<Task>(typeof(Game1), nameof(_newDayTask)).GetValue();
|
||||
private Color bgColor => SGame.Reflection.GetField<Color>(this, nameof(bgColor)).GetValue();
|
||||
public RenderTarget2D screenWrapper => SGame.Reflection.GetProperty<RenderTarget2D>(this, "screen").GetValue(); // deliberately renamed to avoid an infinite loop
|
||||
public BlendState lightingBlend => SGame.Reflection.GetField<BlendState>(this, nameof(lightingBlend)).GetValue();
|
||||
private readonly Action drawFarmBuildings = () => SGame.Reflection.GetMethod(SGame.Instance, nameof(drawFarmBuildings)).Invoke();
|
||||
private readonly Action drawHUD = () => SGame.Reflection.GetMethod(SGame.Instance, nameof(drawHUD)).Invoke();
|
||||
private readonly Action drawDialogueBox = () => SGame.Reflection.GetMethod(SGame.Instance, nameof(drawDialogueBox)).Invoke();
|
||||
private readonly Action renderScreenBuffer = () => SGame.Reflection.GetMethod(SGame.Instance, nameof(renderScreenBuffer)).Invoke();
|
||||
// ReSharper restore ArrangeStaticMemberQualifier, ArrangeThisQualifier, InconsistentNaming
|
||||
|
||||
|
||||
|
@ -182,7 +182,7 @@ namespace StardewModdingAPI.Framework
|
|||
this.SContentManager = new SContentManager(this.Content.ServiceProvider, this.Content.RootDirectory, Thread.CurrentThread.CurrentUICulture, null, this.Monitor, reflection);
|
||||
this.Content = new ContentManagerShim(this.SContentManager, "SGame.Content");
|
||||
Game1.content = new ContentManagerShim(this.SContentManager, "Game1.content");
|
||||
reflection.GetPrivateField<LocalizedContentManager>(typeof(Game1), "_temporaryContent").SetValue(new ContentManagerShim(this.SContentManager, "Game1._temporaryContent")); // regenerate value with new content manager
|
||||
reflection.GetField<LocalizedContentManager>(typeof(Game1), "_temporaryContent").SetValue(new ContentManagerShim(this.SContentManager, "Game1._temporaryContent")); // regenerate value with new content manager
|
||||
}
|
||||
|
||||
/****
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using System.Reflection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>A private field obtained through reflection.</summary>
|
||||
/// <typeparam name="TValue">The field value type.</typeparam>
|
||||
[Obsolete("Use " + nameof(IReflectedField<TValue>) + " instead")]
|
||||
public interface IPrivateField<TValue>
|
||||
{
|
||||
/*********
|
||||
|
@ -23,4 +25,4 @@ namespace StardewModdingAPI
|
|||
//// <param name="value">The value to set.</param>
|
||||
void SetValue(TValue value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System.Reflection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>A private method obtained through reflection.</summary>
|
||||
[Obsolete("Use " + nameof(IReflectedMethod) + " instead")]
|
||||
public interface IPrivateMethod
|
||||
{
|
||||
/*********
|
||||
|
@ -24,4 +26,4 @@ namespace StardewModdingAPI
|
|||
/// <param name="arguments">The method arguments to pass in.</param>
|
||||
void Invoke(params object[] arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using System.Reflection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>A private property obtained through reflection.</summary>
|
||||
/// <typeparam name="TValue">The property value type.</typeparam>
|
||||
[Obsolete("Use " + nameof(IPrivateProperty<TValue>) + " instead")]
|
||||
public interface IPrivateProperty<TValue>
|
||||
{
|
||||
/*********
|
||||
|
@ -23,4 +25,4 @@ namespace StardewModdingAPI
|
|||
//// <param name="value">The value to set.</param>
|
||||
void SetValue(TValue value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>A field obtained through reflection.</summary>
|
||||
/// <typeparam name="TValue">The field value type.</typeparam>
|
||||
public interface IReflectedField<TValue>
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The reflection metadata.</summary>
|
||||
FieldInfo FieldInfo { get; }
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Get the field value.</summary>
|
||||
TValue GetValue();
|
||||
|
||||
/// <summary>Set the field value.</summary>
|
||||
//// <param name="value">The value to set.</param>
|
||||
void SetValue(TValue value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>A method obtained through reflection.</summary>
|
||||
public interface IReflectedMethod
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The reflection metadata.</summary>
|
||||
MethodInfo MethodInfo { get; }
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Invoke the method.</summary>
|
||||
/// <typeparam name="TValue">The return type.</typeparam>
|
||||
/// <param name="arguments">The method arguments to pass in.</param>
|
||||
TValue Invoke<TValue>(params object[] arguments);
|
||||
|
||||
/// <summary>Invoke the method.</summary>
|
||||
/// <param name="arguments">The method arguments to pass in.</param>
|
||||
void Invoke(params object[] arguments);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>A property obtained through reflection.</summary>
|
||||
/// <typeparam name="TValue">The property value type.</typeparam>
|
||||
public interface IReflectedProperty<TValue>
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The reflection metadata.</summary>
|
||||
PropertyInfo PropertyInfo { get; }
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Get the property value.</summary>
|
||||
TValue GetValue();
|
||||
|
||||
/// <summary>Set the property value.</summary>
|
||||
//// <param name="value">The value to set.</param>
|
||||
void SetValue(TValue value);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,62 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace StardewModdingAPI
|
||||
{
|
||||
/// <summary>Provides an API for accessing private game code.</summary>
|
||||
/// <summary>Provides an API for accessing inaccessible code.</summary>
|
||||
public interface IReflectionHelper : IModLinked
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Get an 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 field is not found.</param>
|
||||
IReflectedField<TValue> GetField<TValue>(object obj, string name, bool required = true);
|
||||
|
||||
/// <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 field is not found.</param>
|
||||
IReflectedField<TValue> GetField<TValue>(Type type, string name, bool required = true);
|
||||
|
||||
/// <summary>Get an 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 property is not found.</param>
|
||||
IReflectedProperty<TValue> GetProperty<TValue>(object obj, string name, bool required = true);
|
||||
|
||||
/// <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 property is not found.</param>
|
||||
IReflectedProperty<TValue> GetProperty<TValue>(Type type, string name, bool required = true);
|
||||
|
||||
/// <summary>Get an 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 field is not found.</param>
|
||||
IReflectedMethod GetMethod(object obj, string name, bool required = true);
|
||||
|
||||
/// <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 field is not found.</param>
|
||||
IReflectedMethod GetMethod(Type type, string name, bool required = true);
|
||||
|
||||
/*****
|
||||
** Obsolete
|
||||
*****/
|
||||
/// <summary>Get a private 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>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetField) + " instead")]
|
||||
IPrivateField<TValue> GetPrivateField<TValue>(object obj, string name, bool required = true);
|
||||
|
||||
/// <summary>Get a private static field.</summary>
|
||||
|
@ -20,6 +64,7 @@ namespace StardewModdingAPI
|
|||
/// <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>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetField) + " instead")]
|
||||
IPrivateField<TValue> GetPrivateField<TValue>(Type type, string name, bool required = true);
|
||||
|
||||
/// <summary>Get a private instance property.</summary>
|
||||
|
@ -27,6 +72,7 @@ namespace StardewModdingAPI
|
|||
/// <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>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetProperty) + " instead")]
|
||||
IPrivateProperty<TValue> GetPrivateProperty<TValue>(object obj, string name, bool required = true);
|
||||
|
||||
/// <summary>Get a private static property.</summary>
|
||||
|
@ -34,6 +80,7 @@ namespace StardewModdingAPI
|
|||
/// <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>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetProperty) + " instead")]
|
||||
IPrivateProperty<TValue> GetPrivateProperty<TValue>(Type type, string name, bool required = true);
|
||||
|
||||
/// <summary>Get the value of a private instance field.</summary>
|
||||
|
@ -42,6 +89,7 @@ namespace StardewModdingAPI
|
|||
/// <param name="name">The field name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the private field is not found.</param>
|
||||
/// <remarks>This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.</remarks>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetField) + " or " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetProperty) + " instead")]
|
||||
TValue GetPrivateValue<TValue>(object obj, string name, bool required = true);
|
||||
|
||||
/// <summary>Get the value of a private static field.</summary>
|
||||
|
@ -50,18 +98,21 @@ namespace StardewModdingAPI
|
|||
/// <param name="name">The field name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the private field is not found.</param>
|
||||
/// <remarks>This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.</remarks>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetField) + " or " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetProperty) + " instead")]
|
||||
TValue GetPrivateValue<TValue>(Type type, string name, bool required = true);
|
||||
|
||||
/// <summary>Get a private 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>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetMethod) + " instead")]
|
||||
IPrivateMethod GetPrivateMethod(object obj, string name, bool required = true);
|
||||
|
||||
/// <summary>Get a private 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>
|
||||
[Obsolete("Use " + nameof(IReflectionHelper) + "." + nameof(IReflectionHelper.GetMethod) + " instead")]
|
||||
IPrivateMethod GetPrivateMethod(Type type, string name, bool required = true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -728,7 +728,7 @@ namespace StardewModdingAPI
|
|||
IMonitor monitor = this.GetSecondaryMonitor(metadata.DisplayName);
|
||||
ICommandHelper commandHelper = new CommandHelper(manifest.UniqueID, metadata.DisplayName, this.CommandManager);
|
||||
IContentHelper contentHelper = new ContentHelper(contentManager, metadata.DirectoryPath, manifest.UniqueID, metadata.DisplayName, monitor);
|
||||
IReflectionHelper reflectionHelper = new ReflectionHelper(manifest.UniqueID, metadata.DisplayName, this.Reflection);
|
||||
IReflectionHelper reflectionHelper = new ReflectionHelper(manifest.UniqueID, metadata.DisplayName, this.Reflection, this.DeprecationManager);
|
||||
IModRegistry modRegistryHelper = new ModRegistryHelper(manifest.UniqueID, this.ModRegistry);
|
||||
ITranslationHelper translationHelper = new TranslationHelper(manifest.UniqueID, manifest.Name, contentManager.GetLocale(), contentManager.GetCurrentLanguage());
|
||||
|
||||
|
|
|
@ -111,6 +111,9 @@
|
|||
<Compile Include="Framework\Exceptions\SAssemblyLoadFailedException.cs" />
|
||||
<Compile Include="Framework\ModLoading\AssemblyLoadStatus.cs" />
|
||||
<Compile Include="Framework\Utilities\ContextHash.cs" />
|
||||
<Compile Include="IReflectedField.cs" />
|
||||
<Compile Include="IReflectedMethod.cs" />
|
||||
<Compile Include="IReflectedProperty.cs" />
|
||||
<Compile Include="Metadata\CoreAssets.cs" />
|
||||
<Compile Include="ContentSource.cs" />
|
||||
<Compile Include="Events\ContentEvents.cs" />
|
||||
|
@ -169,7 +172,7 @@
|
|||
<Compile Include="Framework\Models\ModStatus.cs" />
|
||||
<Compile Include="Framework\Models\SConfig.cs" />
|
||||
<Compile Include="Framework\ModLoading\ModMetadata.cs" />
|
||||
<Compile Include="Framework\Reflection\PrivateProperty.cs" />
|
||||
<Compile Include="Framework\Reflection\ReflectedProperty.cs" />
|
||||
<Compile Include="Framework\RequestExitDelegate.cs" />
|
||||
<Compile Include="Framework\SContentManager.cs" />
|
||||
<Compile Include="Framework\Exceptions\SParseException.cs" />
|
||||
|
@ -198,8 +201,8 @@
|
|||
<Compile Include="Framework\Models\ModDataRecord.cs" />
|
||||
<Compile Include="Framework\ModLoading\AssemblyLoader.cs" />
|
||||
<Compile Include="Framework\Reflection\CacheEntry.cs" />
|
||||
<Compile Include="Framework\Reflection\PrivateField.cs" />
|
||||
<Compile Include="Framework\Reflection\PrivateMethod.cs" />
|
||||
<Compile Include="Framework\Reflection\ReflectedField.cs" />
|
||||
<Compile Include="Framework\Reflection\ReflectedMethod.cs" />
|
||||
<Compile Include="Framework\Reflection\Reflector.cs" />
|
||||
<Compile Include="IManifest.cs" />
|
||||
<Compile Include="IMod.cs" />
|
||||
|
|
Loading…
Reference in New Issue