Reflection ExamplesLearn about the System.Reflection namespace. Use FieldInfo, and call GetMethod and GetProperties.
This page was last reviewed on Nov 14, 2022.
Reflection. A .NET program that uses reflection can examine it own surface—its fields, methods, types. Reflection is a powerful feature in C#, but it must be used with care.
Reflection issues. With reflection, we usually have a significant performance loss. And the code that reflects can be hard to maintain.
Fields. We loop through fields and display their names and values. System.Reflection provides a way to enumerate fields and properties. It can access fields by name.
Detail 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.
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(); } }
Height (int) = 100 Width (int) = 50 Weight (int) = 300 Name (string) = Perl
SetValue. This accesses fields by their names. With System.Reflection, we can take a string that represents a target field, and then change the actual value of that field.
Detail 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 Literal
Note The first argument to SetValue() is the object instance you want to mutate. For a static field this can be left as null.
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); } }
Methods. What should we do if we have the name of a method in string format and want to call the method? We can use GetMethod. Then we invoke the MethodInfo we acquire from it.
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.
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 }); } } }
Inform:parameter=Sam Inform:parameter=Perls
MethodInfo, Invoke. An instance method can be called by its name. With the MethodInfo type, we call the Invoke method. We must provide an instance expression.
Detail 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.
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); } } } }
Win {You're a winner} Lose Draw ToString Equals GetHashCode GetType
Reflection, properties. Reflection can get the values of properties. We loop over properties and determine their values. With reflection a property can be referenced by a string.
Start The Program class has 2 instance properties: the Awesome property and the Perls property (sorry for the names).
Detail We evaluate typeof(Program) and call GetProperties() on the Type returned. On the PropertyInfo type, we use Name and GetValue.
Detail This requires the instance of the object we are searching. If you are using a static type, you can just pass null.
Detail GetValue() returns an object. We use the is-cast to determine which we have, and then print custom messages to the Console.
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); } } } }
Int: Awesome = 7 String: Perls = Hello
Assembly. The Assembly type contains many Type instances. We can call GetCallingAssembly. And on Assembly, we can get an array of types, or a specific, named type.
Detail 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.
Detail The GetType method next receives a string, and returns a Type pointer if one of that name is located.
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); } }
Box Program Box
Benchmark, reflection. It is tempting to use reflection in places where it is not necessary. But this may come at a great performance cost.
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.
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")); } }
161.84 ns GetField, SetValue 0.53 ns =
Types. The "Type" type is important when reflecting. We cover the GetType method that is found on the object type. GetType helps us discover the object hierarchy.
Typeof. This operator uses reflection to return the Type of a variable. We use the typeof operator in most code that requires complicated reflection capabilities.
Sizeof. This operator exposes information about the implementation of types. It does not require the System.Reflection namespace. But it is related to reflection.
Default. This operator returns the default value for a type. It is used when developing classes such as generics. The default value of an int is zero.
Discussion. Many programs must maintain a set of preference values that are assigned during startup or later execution. You can store these preferences in an array.
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).
Field instructions. When you use fields (with stsfld or ldsfld) you are creating exception-free code. Reading fields, because it does not invoke executable code, will not throw exceptions.
A summary. Programs that use reflection can look inside themselves to see their inner workings. This capacity lends them unique and powerful features.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
No updates found for this page.
© 2007-2023 Sam Allen.