C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Example: In the .NET Framework, a program is compiled into an assembly containing metadata. This is an abstract binary representation.
And: We can explore the string data stored in the executable to access field and property names.
Next: This static class has 4 fields of type Int32 and String. We get the FieldInfo objects for those fields and then display them.
StaticInt, uintC# program that uses reflection on fields
using System;
using System.Reflection;
static class ReflectionTest
{
public static int Height;
public static int Width;
public static int Weight;
public static string Name;
public static void Write()
{
Type type = typeof(ReflectionTest);
// Obtain all fields with type pointer.
FieldInfo[] fields = type.GetFields();
foreach (var field in fields)
{
string name = field.Name;
object temp = field.GetValue(null);
// See if it is an integer or string.
if (temp is int)
{
int value = (int)temp;
Console.Write(name);
Console.Write(" (int) = ");
Console.WriteLine(value);
}
else if (temp is string)
{
string value = temp as string;
Console.Write(name);
Console.Write(" (string) = ");
Console.WriteLine(value);
}
}
}
}
class Program
{
static void Main()
{
// Set values.
ReflectionTest.Height = 100;
ReflectionTest.Width = 50;
ReflectionTest.Weight = 300;
ReflectionTest.Name = "Perl";
// Invoke reflection methods.
ReflectionTest.Write();
}
}
Output
Height (int) = 100
Width (int) = 50
Weight (int) = 300
Name (string) = Perl
First: This program has a public static int field with the identifier _field. We get the type of the class using the typeof operator.
Then: We call GetField with the string literal "_field" as the argument. We invoke the SetValue method.
String LiteralNote: The first argument to SetValue() is the object instance you want to mutate. For a static field this can be left as null.
NullC# program that uses SetValue on FieldInfo
using System;
using System.Reflection;
class Program
{
public static int _field; // Must be public!
static void Main()
{
// Get FieldInfo on Program type.
FieldInfo info = typeof(Program).GetField("_field");
// Set static field to this value.
info.SetValue(null, 1969);
// Now see what _field equals.
Console.WriteLine(_field);
}
}
Output
1969
Note: GetMethod references methods with only a string name. With it we call a method whose name equals this string.
Here: We want to call the Inform static method by using the string "Inform" and we want to call it twice with different parameters.
C# program that uses GetMethod
using System;
using System.Reflection;
static class Methods
{
public static void Inform(string parameter)
{
Console.WriteLine("Inform:parameter={0}", parameter);
}
}
class Program
{
static void Main()
{
// Name of the method we want to call.
string name = "Inform";
// Call it with each of these parameters.
string[] parameters = { "Sam", "Perls" };
// Get MethodInfo.
Type type = typeof(Methods);
MethodInfo info = type.GetMethod(name);
// Loop over parameters.
foreach (string parameter in parameters)
{
info.Invoke(null, new object[] { parameter });
}
}
}
Output
Inform:parameter=Sam
Inform:parameter=Perls
Example: GetMethods() on the Type class returns all the public instance methods on a type by default.
Here: We get an array of MethodInfo instances of all the public Program class methods.
And: We print their names, but also test for the Win method. If we find this method, we call Invoke on it.
C# program that calls Invoke on MethodInfo
using System;
using System.Reflection;
class Program
{
public void Win()
{
Console.WriteLine("{You're a winner}");
}
public void Lose()
{
}
public void Draw()
{
}
static void Main()
{
// Instance used for Invoke.
Program program = new Program();
// Get methods.
MethodInfo[] methods = typeof(Program).GetMethods();
foreach (MethodInfo info in methods)
{
Console.WriteLine(info.Name);
// Call Win method.
if (info.Name == "Win")
{
info.Invoke(program, null);
}
}
}
}
Output
Win
{You're a winner}
Lose
Draw
ToString
Equals
GetHashCode
GetType
Start: The Program class has 2 instance properties: the Awesome property and the Perls property (sorry for the names).
Main: We evaluate typeof(Program) and call GetProperties() on the Type returned. On the PropertyInfo type, we use Name and GetValue.
GetValue: This requires the instance of the object we are searching. If you are using a static type, you can just pass null.
Casting: GetValue() returns an object. We use the is-cast to determine which we have, and then print custom messages to the Console.
IsConsoleC# program that uses reflection on properties
using System;
using System.Reflection;
class Program
{
public int Awesome { get; set; }
public string Perls { get; set; }
static void Main()
{
// Create an instance of Program.
Program programInstance = new Program();
programInstance.Awesome = 7;
programInstance.Perls = "Hello";
// Get type.
Type type = typeof(Program);
// Loop over properties.
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
// Get name.
string name = propertyInfo.Name;
// Get value on the target instance.
object value = propertyInfo.GetValue(programInstance, null);
// Test value type.
if (value is int)
{
Console.WriteLine("Int: {0} = {1}", name, value);
}
else if (value is string)
{
Console.WriteLine("String: {0} = {1}", name, value);
}
}
}
}
Output
Int: Awesome = 7
String: Perls = Hello
Example: This file includes the System.Reflection namespace. We call Assembly.GetCallingAssembly() to get the current assembly.
And: With GetTypes, we receive an array of Type instances. We loop with foreach through these elements.
GetType: The GetType method next receives a string, and returns a Type pointer if one of that name is located.
C# program that uses Assembly type
using System;
using System.Reflection;
class Box
{
}
class Program
{
static void Main()
{
// Get assembly.
Assembly assembly = Assembly.GetCallingAssembly();
// Get array of types.
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
Console.WriteLine(t);
}
Console.WriteLine();
// Get type by name.
string name = "Box";
Type type = assembly.GetType(name);
Console.WriteLine(type);
}
}
Output
Box
Program
Box
Version 1: We use reflection (GetField, SetValue) to set the value of an integer property on the Program type.
Version 2: Use just as sign the value to the property directly in C# code. The performance is better in this version.
Result: The version that uses reflection to look up a field and set it is several hundred times slower.
C# program that tests reflection performance
using System;
using System.Diagnostics;
using System.Reflection;
class Program
{
public static int _field;
const int _max = 1000000;
static void Main()
{
// Version 1: use reflection to set field by name.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
FieldInfo info = typeof(Program).GetField("_field");
info.SetValue(null, 1000);
}
s1.Stop();
// Version 2: set field directly.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
_field = 1000;
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
}
Output
161.84 ns GetField, SetValue
0.53 ns =
However: You can instead loop through fields with reflection and print their values to the console or web page.
Also: This approach improves performance when assigning or reading the values (because they are fields).