Dynamically Create Instance of a Type on Run Time Using Reflection in C#
Reflection is the process of describing the metadata of types, methods and fields in a code. It helps to get information about loaded assemblies and elements within it like classes, methods etc. According to microsoft documentation, Reflection provides objects (of type Type) that describe assemblies, modules, and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. If you are using attributes in your code, reflection enables you to access them.
While creating test automation framework, we will come across scenarios where we need to create instance of an objects on run time, need to examine and instantiate types in an assembly, access attributes etc. One of the common usecase is when we create a generic framework, which will allow users to specify class name in feature files and handle it without doing any further modification. Let us look at how we can achieve those.
Examples of Reflection
How to get Type of an object
// Using GetType to obtain type information:stringi="Hello World";Typetype=i.GetType();Console.WriteLine(type);
This will print System.String
How to get Details loaded assembly
// Using Reflection to get information of an Assembly:Assemblyinfo=typeof(string).Assembly;Console.WriteLine(info);
This will print System.Private.CoreLib, Version=22.214.171.124, Culture=neutral
How to create instance of a Class
Creating an instance of inbuilt class can be done like below.
// create instance of class DateTimeDateTimedateTime=(DateTime)Activator.CreateInstance(typeof(DateTime));
Creating an instance of custom class is a multistep process
// 1. Load the dll having the classAssemblytestAssembly=Assembly.LoadFile(@"PathToDll\Test.dll");// get type of class from just loaded assemblyTypeclassType=testAssembly.GetType("Test.CustomClass");// create instance of classobjectclassInstance=Activator.CreateInstance(classType);
Activator.CreateInstance has detailed explanation of various constructors here
How to call a method from created instance
// fullNameOfClass is the complete name of the class including all namespaces. It is also assumed that , it is in same assembly, there is a default constructor and method doesn't need any parameters.varclassHandle=Activator.CreateInstance(null,fullNameOFClass,true,0,null,null,null,null);varclassInstance=(className)classHandle.Unwrap();// Unwrap in above activate an object in another AppDomain, retrieve a proxy to it with the Unwrap method, and use the proxy to access the remote object. More details [here](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.remoting.objecthandle.unwrap?view=net-5.0)//If it is in same Appdomain, we will not need to castTypet=classInstance.GetType();//Invoking Method without parameters. If parameters are needed, pass them as an object arrayMethodInfomethod=t.GetMethod(methodName);method.Invoke(p,null);//Getting Field valueFieldInfofield=t.GetField(fieldName);returnfield.GetValue(p);
Seeing this in an example will help to make our understanding clear.
Use reflection to create an instance of above calculator class
We will start with creating a class Handle by passing full name of teh class. Then we get details of Add method. Then we call Add method by passing parameters as an object array. It will return the value as defined in the class