If you have scripting language that allows you to call C# (e.g. Powershell), or if you want to call undocumented private methods, then you need to learn how to use Reflection.
It’s a way of programatically examining and calling code from an assembly (.dll/.exe) at runtime.
The examples here are in C#, but the concepts apply when you are using scripting languages that use .NET.
How would you use classes from a different dll without importing it?
You could use Assembly.UnsafeLoadFrom("path to dll");
this will return an Assembly
object, which you can use to create instances programatically.
var targetAssmbly = Assembly.UnsafeLoadFrom(@"\\pathTo\your.dll");
var instance = targetAssmbly.CreateInstance("Some.Class.In.Assembly");
Let’s start with two fundamental methods CreateInstance
and GetType
. These are instance methods in System.Reflection.Assembly
.
CreateInstance is equivalent to programatically making a new object.
//this is the Reflection equivalent of doing var x = new System.Collections.ArrayList();
var x = "".GetType().Assembly.CreateInstance("System.Collections.ArrayList");
GetType is equivalent to getting a handle to a class so that you can call a static method on it.
//if you just want to call a static method
//(such as System.Convert.FromBase64String)
var convertType = "".GetType().Assembly.GetType("System.Convert")
Note that there is also a Type.GetType(string)
static method that searches the current assembly for that Type. This can also be used.
Note that you are only allowed to access classes from the same assembly as ‘String’ (mscorlib.dll)
To invoke any method with parameters, you need to pass in the parameter list as an array of C# objects.
But in most scripting languages, there is no notion of a “type”. So how do you create a C# array of C# objects?
Answer: Use the ArrayList.Add(object)
function to add objects of any type, then use the ArrayList.ToArray()
to convert it to a C# array of objects.
There are two options that you can use to invoke methods.
- with the method name: Type.GetMethod("nameOfMethod").Invoke(...)
- get all the methods of the class, then select which one you want to invoke (by index): Type.GetMethods()[3].Invoke(...)
Questions you might have are:
- how do you invoke a method on a class vs an instance?
- how do you invoke async methods?
- how do you invoke private methods?
//Example of how to dynamically invoke 'System.Convert.FromBase64String()'
"".GetType().Assembly.GetType("System.Convert").GetMethod("FromBase64String").Invoke(null, new string[]{"base64 string"});
The first argument to Invoke
is the object you want to target. In this case, we are not calling this method on an object, so it is null
.
The second argument to Invoke
is the parameter list for the method FromBase64String
. It must be passed as an Object[]
.
Here is another example of reflectively invoking a method on an instance of an object. Note the dynamic
declaration of resultsToAwait
.
var targetAssmbly = Assembly.UnsafeLoadFrom(@"\\pathTo\your.dll");
var instance = targetAssmbly.CreateInstance("Some.Class.In.Assembly");
dynamic resultsToAwait = targetAssmbly.GetType("Some.Class.In.Assembly").GetMethod("GetStuffAsync").Invoke(instance, null);
//'null' because GetStuffAsync does not need parameters
IEnumerable<dynamic> results = await resultsToAwait;
//assuming that the results return an IEnumerable, you have to check the return type.
One reason for using this is if there are overloaded methods with the same number of parameters.
For example, Assembly.Load(AssemblyName)
and Assembly.Load(byte[])
The first step is to list the methods - note that the methods can appear in a different order when you are running the code on a different machine.
This will list all the public methods of a given type.
MethodInfo[] allMethods = "".GetType().GetMethods();
You need to use these objects called ‘BindingFlags’ and use the method: GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
var privateMethods = "".GetType()
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
get yourself on the email list
comments powered by Disqus