Reflection code snippets tested under .NET Core 2.

What is reflection and how can you benefit from it

Reflection allows a program to inspect or modify itself during runtime. In practice it means that you can do all sorts of stuff on objects/properties including checking type of an object at runtime (typeof), listing all fields of an object without knowing variable names (including private members), modifying properties of an object (also including private members), instantiating object by class name and ivoking its methods dynamically, inspecting attributes attached to objects/properties, finding all classes implementing given interface in an assembly and so on.

In general reflection is not used too often in web/mobile programming, but it’s almost certainly extensively used by your framework or in certain types of plugins, so you are using it indirectly almost all the time.

Realistic use cases

Plugins – oftentimes we write plugins for another programs, which basically are a DLLs implementing specific programming interfaces. These programs use reflection to load our plugin file, look for classes implementing interfaces and execute methods based on events.

Utilities – packages like Automapper use reflection to map properties from one object to other, it reads and writes properties dynamically, without prior knowledge of what’s inside your classes.

Attributes – attributes are resolved dynamically in your whole app e.g. DisplayAttribute is read by input tag helper (or Html.DisplayFor) and then it’s printed out (or localized and then printed). If you’ve ever wondered how unit tests are run (the [Test]/[Fact] of xUnit.net) then you have your answer now, software looks for classes decorated with a TestClass attribute, instantiate it, then it runs all methods decorated with a Test attribute.

Dependency injection – runtime type resolution of required dependencies for the purpose of decoupling code.

Security – a little less realistic, but still possible. In theory attacker could use reflection to modify variables of your program to produce errors or unwanted behavior like toggling private bool validLogin;, causing infinite loop or getting read/write access to files. Another possibility it to read sensitive information e.g. api keys or passwords hardcoded in you app.

Bug fixing – acually this is a less realistic example. Theoretically if there is a bug in component which is done by someone else and you can’t wait until it’s fixed, you can try to repair it by modifying variables of an object, but for that you’d need to know specific use case and inner workings of broken component.

Security

Reflection can be used to get information about types and members without restrictions, but using reflection to get member values is restricted. Only trusted code can be used to access security critical and nonpublic members. Only permitted code may access safe-critical members. If you want to know more then see security considerations.

The other thing is that there aren’t many interesting things with it, so it’d rather be pretty difficult to abuse an app through reflection and it probably wouldn’t be too serious.

As it goes for hardcoding sensitive data you shouldn’t do it anyway. If someone has access to your soft then she/he can get it by means of reverse engineering regardless of reflection.

To sum up this section: I think that you shouldn’t worry about someone using reflection on your code in general, as always keep in mind good security practices and don’t overthink reflection related security issues (in general). Only way to use reflection to break something is to run bad code in full trust mode.

Snippets

It’s time for some snippets. Everything starts with Type of your instance or type.

1
2
3
4
5
6
7
8
// in case of instance
instance.GetType();
//in case of type
typeof(MyClass);
// you can also get type by name
var type = Type.GetType("App.Namespace.MyClass");
// if the class is nested then use +
var type = Type.GetType("App.Namespace.MyClass+NestedClass");

Obviously you use GetType if you want to retrieve instance members. If you only need to work on metadata of a type (meaning you don’t need to inspect object to get variable value) you use the typeof

How to create an instance dynamically

1
var instance = Activator.CreateInstance<MyClass>();

Check if object is of generic type

1
var isGeneric = instance.GetType().IsGenericType;

Check if object is of specific generic type e.g. ICollection<>

1
var isGenericICollection = instance.GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>));

How to use reflection to call a method

You need to call Invoke, first param is instance, second is an array of parameters. If there are no parameters then use null.

1
2
3
var method = instance.GetType().GetMethod("MyMethod");
var parameters = new [] { "John", "Doe" };
var result = method.Invoke(instance, parameters);

How to use reflection to call a generic method

It’s similiar to regular method call, but you have to perform additional operation to make it generic.

1
2
3
4
var method = instance.GetType().GetMethod("MyMethod");
var generic = method.MakeGenericMethod(typeof(string));
var parameters = new [] { "Jane", "Doe" };
var result = generic.Invoke(instance, parameters);

How to use reflection to invoke static method

Similar to regular method call, but you pass null instead of instance type.

1
2
3
var method = typeof(MyClass).GetMethod("MyMethod");
var parameters = new object[] { 1, DateTime.Now };
var result = method.Invoke(null, parameters);

How to user reflection to invoke private method

1
2
var method = typeof(MyClass).GetMethod("MyPrivateMethod", BindingFlags.Instance | BindingFlags.NonPublic);
var result = method.Invoke(instance, null);

How to invoke overloaded method

Executing MyMethod which has one string parameter.

1
2
var method = instance.GetType().GetMethod("MyMethod", new Type[] { typeof(string) });
var result = method.Invoke(instance, new object[] { "myString" });

How to get properties names

You can get it via instance:

1
2
var obj = new MyClass();
var names = obj.GetType().GetProperties().Select(property => property.Name);

or directly from type definition:

1
var names = typeof(MyClass).GetProperties().Select(property => property.Name);

Keep in mind that since C#6 we can use nameof to get property names as strings.

How to use reflection to get property value

1
2
3
4
var property = instance
        .GetType()
        .GetProperty(nameof(MyClass.MyProperty));
var value = property.GetValue(instance, null);

How to use reflection to set property value

1
2
3
4
var property = instance
 .GetType()
 .GetProperty(nameof(MyClass.MyProperty));
property.SetValue(instance, "NewValue", null);

How do i retrieve attributes [names] from variables

1
2
3
var property = typeof(MyClass).GetProperty("MyProperty");
 var attributes = property.GetCustomAttributes();
 var names = attributes.Select(i => i.GetType().Name);

How to get a list of implemented interfaces

1
var interfaces = typeof(MyClass).GetInterfaces();

How to get a list of methods

1
var methods = typeof(MyClass).GetMethods();

How to get return type of a method

1
var returnType = typeof(MyClass).GetMethod("MyMethod").ReturnType;

How to get parameters of method

1
var methodParams = typeof(MyClass).GetMethod(nameof(MyClass.MyMethod)).GetParameters();

How to load assembly

Typically you use different method of loading an assembly depending on use case (refer to documentation).

1
2
3
4
var assembly = Assembly.Load("AssemblyName");
var assembly = typeof(MyClass).Assembly;
var assembly = Assembly.GetExecutingAssembly();
var assembly = Assembly.LoadFrom("c:/lib.dll");

How to list all types from assembly

1
var types = assembly.GetTypes();

How to find all types implementing interface

1
2
var t = typeof(IInterface);
var types = assembly.GetTypes().Where(i => t.IsAssignableFrom(i));

How to get all properties with attribute

1
var properties = typeof(MyClass).GetProperties().Where(property => Attribute.IsDefined(property, typeof(MyAttribute)));

Summary

Reflection is a powerful tool, yet there seem to be only a few real world use cases. In your daily/regular programming practice you most likely won’t use it too much, unless you’re a framework software developer etc. It’s certianly not a tool fit for all kind of jobs, but sometimes you just need it.