Changes

Jump to navigation Jump to search
m
Text replacement - "tt>" to "samp>"
Line 1: Line 1:  
{{../../header}}
 
{{../../header}}
   −
The reflection API lets you access fields, properties, or methods you otherwise couldn't access. You can use it from <tt>helper.Reflection</tt> in your entry method, or <tt>this.Helper.Reflection</tt> elsewhere in your entry class.
+
The reflection API lets you access fields, properties, or methods you otherwise couldn't access. You can use it from <samp>helper.Reflection</samp> in your entry method, or <samp>this.Helper.Reflection</samp> elsewhere in your entry class.
    
==Intro==
 
==Intro==
Line 8: Line 8:  
==Basic reflection==
 
==Basic reflection==
 
===Overview===
 
===Overview===
SMAPI provides three overloaded methods to access code: <tt>GetField</tt>, <tt>GetProperty</tt>, and <tt>GetMethod</tt>. Each one takes three arguments:
+
SMAPI provides three overloaded methods to access code: <samp>GetField</samp>, <samp>GetProperty</samp>, and <samp>GetMethod</samp>. Each one takes three arguments:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 14: Line 14:  
! purpose
 
! purpose
 
|-
 
|-
| <tt>obj</tt> or <tt>type</tt>
+
| <samp>obj</samp> or <samp>type</samp>
 
| The instance (or type if static) which has the private field/property/method you want to access.
 
| The instance (or type if static) which has the private field/property/method you want to access.
 
|-
 
|-
| <tt>name</tt>
+
| <samp>name</samp>
 
| The name of the private field/property/method.
 
| The name of the private field/property/method.
 
|-
 
|-
| <tt>required</tt>
+
| <samp>required</samp>
| Whether to throw a descriptive exception if the field/property/method isn't found. Default true. If set to false, it will return <tt>null</tt> instead and you should validate it yourself.
+
| Whether to throw a descriptive exception if the field/property/method isn't found. Default true. If set to false, it will return <samp>null</samp> instead and you should validate it yourself.
 
|}
 
|}
   Line 27: Line 27:     
===Fields and properties===
 
===Fields and properties===
<tt>GetField</tt> and <tt>GetProperty</tt> are used the same way. Both return an object with two methods: <tt>GetValue</tt> returns the current field/property value, and <tt>SetValue</tt> overrides their value.
+
<samp>GetField</samp> and <samp>GetProperty</samp> are used the same way. Both return an object with two methods: <samp>GetValue</samp> returns the current field/property value, and <samp>SetValue</samp> overrides their value.
    
You can get the value directly:
 
You can get the value directly:
<source lang="c#">
+
<syntaxhighlight lang="c#">
 
// get value of instance field
 
// get value of instance field
 
bool wasPet = this.Helper.Reflection.GetField<bool>(pet, "wasPetToday").GetValue();
 
bool wasPet = this.Helper.Reflection.GetField<bool>(pet, "wasPetToday").GetValue();
</source>
+
</syntaxhighlight>
    
Or you can keep a reference to the reflection data, and change the value separately:
 
Or you can keep a reference to the reflection data, and change the value separately:
<source lang="c#">
+
<syntaxhighlight lang="c#">
 
// set value of static field
 
// set value of static field
 
IReflectedField<int> soundTimer = this.Helper.Reflection.GetField<int>(typeof(Junimo), "soundTimer");
 
IReflectedField<int> soundTimer = this.Helper.Reflection.GetField<int>(typeof(Junimo), "soundTimer");
 
soundTimer.SetValue(100);
 
soundTimer.SetValue(100);
</source>
+
</syntaxhighlight>
    
If you need to access the field/property repeatedly, keeping the reflection object will improve performance.
 
If you need to access the field/property repeatedly, keeping the reflection object will improve performance.
    
===Methods===
 
===Methods===
<tt>GetMethod</tt> returns an object with one overloaded method. The <tt>Invoke</tt> comes in two forms:
+
<samp>GetMethod</samp> returns an object with one overloaded method. The <samp>Invoke</samp> comes in two forms:
* <tt>Invoke()</tt> calls a method with no return value.
+
* <samp>Invoke()</samp> calls a method with no return value.
* <tt>Invoke&lt;T&gt;()</tt> calls a method which returns a value, where <tt>T</tt> is the expected return type.
+
* <samp>Invoke&lt;T&gt;()</samp> calls a method which returns a value, where <samp>T</samp> is the expected return type.
   −
For example, this calls the private <tt>TV.getFortuneForecast</tt> method and stores the value it returns:
+
For example, this calls the private <samp>TV.getFortuneForecast</samp> method and stores the value it returns:
<source lang="c#">
+
<syntaxhighlight lang="c#">
 
string forecast = this.Helper.Reflection
 
string forecast = this.Helper.Reflection
 
   .GetMethod(new TV(), "getFortuneForecast")
 
   .GetMethod(new TV(), "getFortuneForecast")
 
   .Invoke<string>();
 
   .Invoke<string>();
</source>
+
</syntaxhighlight>
   −
If the method expects arguments, you can just add those to the <tt>Invoke</tt> method:
+
If the method expects arguments, you can just add those to the <samp>Invoke</samp> method:
<source lang="c#">
+
<syntaxhighlight lang="c#">
 
Vector2 spawnTile = new Vector2(25, 25);
 
Vector2 spawnTile = new Vector2(25, 25);
 
this.helper.Reflection
 
this.helper.Reflection
 
   .GetMethod(Game1.getFarm(), "doSpawnCrow")
 
   .GetMethod(Game1.getFarm(), "doSpawnCrow")
 
   .Invoke(spawnTile);
 
   .Invoke(spawnTile);
</source>
+
</syntaxhighlight>
    
==Advanced reflection==
 
==Advanced reflection==
 
If you need to do more, you can access the underlying C# reflection types:
 
If you need to do more, you can access the underlying C# reflection types:
<source lang="c#">
+
<syntaxhighlight lang="c#">
 
FieldInfo field = this.Helper.Reflection.GetField<string>(…).FieldInfo;
 
FieldInfo field = this.Helper.Reflection.GetField<string>(…).FieldInfo;
 
MethodInfo method = this.Helper.Reflection.GetMethod(…).MethodInfo;
 
MethodInfo method = this.Helper.Reflection.GetMethod(…).MethodInfo;
</source>
+
</syntaxhighlight>
    
Or even use [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection C# reflection] directly. Note that SMAPI adds caching and optimisations which you'll need to handle yourself if you do this.
 
Or even use [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection C# reflection] directly. Note that SMAPI adds caching and optimisations which you'll need to handle yourself if you do this.
105,686

edits

Navigation menu