C# Reflection

 In C#, reflection is a process to get metadata of a type at runtime. The System.Reflection namespace contains required classes for reflection such as:

  • Type
  • MemberInfo
  • ConstructorInfo
  • MethodInfo
  • FieldInfo
  • PropertyInfo
  • TypeInfo
  • EventInfo
  • Module
  • Assembly
  • AssemblyName
  • Pointer etc.

The System.Reflection.Emit namespace contains classes to emit metadata

Reflection in C# 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.

Reflection is needed when you want to determine or inspect the content of an assembly. Here, content means the metadata of an assembly like what are the methods in that assembly, what are the properties in that assembly, are they public, are they private, etc


How to Implement Reflection in C#?

So, now we are going to write a simple example implementing reflection in C# language. So, first, create a console application with the name ReflectionDemo. And to this console application, let us add a class library project with the name ReflectionDemoClassLibrary. Once you add the Class Library Project, your solution should look like the following.




As you can see, the Class Library Project is created with a class called Class1.cs. Now, modify the Class1.cs class file as follows. As you can see, here we have created some private and public fields, some private and public properties, and some private and public methods.


Now, build the Class Library Project. And once you build the Class Library Project an assembly (with extension .DLL) will be generated inside the Project’s bin=> Debug location then remove the class library from the solution.


Now, what we need to do is, we need to display the Properties, Methods, and Variables of the ReflectionDemoClassLibrary assembly using Reflection.

Get the type of the Object
First, we need to get the reference for the assembly. To get the reference of the assembly we need to use the Assembly.Loadfile method and we need to provide the Path of the assembly (you need to provide the DDL Path where exactly the DLL exists) as follows.

var MyAssembly = Assembly.LoadFile(@”C:\Users\ramana\source\repos\ReflectionSampleDemo\ReflectionDemoClassLibrary\bin\Debug\net6.0\ReflectionDemoClassLibrary.dll”);

Once you get the reference for the assembly, the next step is to get the class reference. What it means once you get the assembly reference, from that assembly reference you need to get the class reference. For this, we need to call the GetType method on the assembly reference, and to this get type method, we need to provide the fully qualified name of the class i.e. namespace.class name is as follows.
var MyType = MyAssembly.GetType(“ReflectionDemoClassLibrary.Class1”);

Once you get the type of the object, then you need to create an instance of that type. To create an instance dynamically we need to use Activator.CreateInstance method and to this method we need to pass the type object as follows.
dynamic MyObject = Activator.CreateInstance(MyType);

Once the object is created, next we need to get the type of the class. To get the type of class, we can use the GetType method as follows.
Type parameterType = MyObject.GetType();

Browse the Metadata of the Object
In this step, we need to browse the metadata of the assembly. To get all the public members we need to use GetMembers, to get all the methods, we need to use GetMethods, to get all the variables or fields, we need to use GetFields, and to get all the properties of the assembly we need to use GetProperties.

Browse the Metadata of the Object

Some of the useful methods are as follows:

GetFields(): It returns all the public fields of the current System.Type.

GetProperties(): It returns all the public properties of the current System.Type.

GetMethods(): It returns all the public methods of the current System.Type.

GetMembers(): It returns all the public members of the current System.Type

The following code is the example



Output:


Here, you can see in all methods it also fetching the object class methods. This is because the object is the superclass of all classes in the .NET Framework. Here, get_P1 and set_P1 are the setter and getter methods of the public property P1,P2. So, this is how you can go and extract metadata of an assembly using Reflection in C#.

Example to show the Type details using Reflection in C#

So, basically what we want to do is, once we get the Type then we want to show the class name, fully qualified class name, and namespace name. For this, we need to call the Name, FullName, and Namespace properties as shown in the below example


output:


So, this is how you can extract the type information of an assembly using Reflection in C#. Now, let us see some other benefits of using Reflection in C#.

Invoke Methods Dynamically using Reflection in C#

One of the good features of reflection is it will inspect the metadata of an assembly and we already discussed this. Another good feature of using Reflection is that we can invoke the members of an assembly in C#. So, if you remember we have defined one public method i.e. Method1 in our class library assembly and we want to invoke that method using reflection in C#.

To invoke the method of assembly using reflection in C#, we need to use the InvokeMember method 

Invoke Methods Dynamically using Reflection in C#

InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args): This method invokes the specified member, using the specified binding constraints and matching the specified argument list. It returns an object representing the return value of the invoked member. This method takes the following parameters:

name: The string containing the name of the constructor, method, property, or field member to invoke. In our case it is Method1.

invokeAttr: A bitmask comprised of one or more System.Reflection.BindingFlags that specify how the search is conducted. The access can be one of the BindingFlags such as Public, NonPublic, Private, InvokeMethod, GetField, and so on. The type of lookup need not be specified. If the type of lookup is omitted, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static is used.

binder: An object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection. -or- A null reference to use the System.Type.DefaultBinder. Note that explicitly defining a System.Reflection.Binder objects may be required for successfully invoking method overloads with variable arguments. Here, we are passing a null value.

target: The object on which to invoke the specified member. In our example, the object is MyObject.

args: An array containing the arguments to pass to the member to invoke. As our method does not take any arguments, so we pass null here.

Note: This method of invocation is completely done at runtime. If the method exists at runtime, it will invoke the method else it will throw an exception. That means Reflection in C# does the complete dynamic invocation of the method during runtime.

Example to Invoke a Method Dynamically using Reflection in C#

output:



What are the real-time uses of Reflection in C#?

If you are creating applications like Visual Studio Editors where you want to show internal details i.e. Metadata of an object using Intelligence.

In unit testing sometimes we need to invoke private methods to test whether the private members are working properly or not.

Sometimes we would like to dump properties, methods, and assembly references to a file or probably show it on a screen.

Late binding can also be achieved by using Reflection in C#. We can use reflection to dynamically create an instance of a type, about which we don’t have any information at compile time. So, Reflection enables us to use code that is not available at compile time.

Consider an example where we have two alternate implementations of an interface. You want to allow the user to pick one or the other using a config file. With reflection, you can simply read the name of the class whose implementation you want to use from the config file, and instantiate an instance of that class. This is another example of late binding using reflection.

Note: Reflection is used to find all types in an assembly and/or dynamically invoke methods in an assembly. This includes information about the type, properties, methods, and events of an object. With Reflection, we can 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




Comments

Popular posts from this blog

Email Sending through O365 using OAuth Protocol

IoT Technology

What is reverse proxy?