adjust reflection API to correctly reflect what it does (#410)

This commit is contained in:
Jesse Plamondon-Willard 2017-12-10 18:05:18 -05:00
parent 80c4d93559
commit 8776d1afa6
19 changed files with 357 additions and 175 deletions

View File

@ -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

View File

@ -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}";

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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,7 +92,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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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
}
/****

View File

@ -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>
{
/*********

View File

@ -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
{
/*********

View File

@ -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>
{
/*********

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());

View File

@ -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" />