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.
|
|
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
|
|
Check if object is of generic type
|
|
Check if object is of specific generic type e.g. 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
.
|
|
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.
|
|
How to use reflection to invoke static method
Similar to regular method call, but you pass null
instead of instance type.
|
|
How to user reflection to invoke private method
|
|
How to invoke overloaded method
Executing MyMethod
which has one string
parameter.
|
|
How to get properties names
You can get it via instance:
|
|
or directly from type definition:
|
|
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
|
|
How to use reflection to set property value
|
|
How do i retrieve attributes [names] from variables
|
|
How to get a list of implemented interfaces
|
|
How to get a list of methods
|
|
How to get return type of a method
|
|
How to get parameters of method
|
|
How to load assembly
Typically you use different method of loading an assembly depending on use case (refer to documentation).
|
|
How to list all types from assembly
|
|
How to find all types implementing interface
|
|
How to get all properties with attribute
|
|
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.