C# Reflection: Everything You Need to Know about Reflection in C# (With Examples)

Reflection in C# is the process of retrieving metadata of types, modules, assemblies, and more during runtime. With reflection, you can dynamically create an instance of a type, associate a type with an existing object, obtain the type of an existing object, and call its methods, fields, and properties.

In this article, we will explore the concept of C# Reflection, its hierarchy, when to use it, and some examples of its implementation.

C# Reflection
Reflection in C#

What Is C# Reflection?

Reflection is a feature in C# that allows you to inspect and manipulate metadata, types, and objects during runtime. Metadata is information about the types defined in a particular assembly and includes information about the types’ properties, methods, and events.

The C# Reflection API provides a set of classes that allow you to examine and manipulate the metadata of the types defined in an assembly. Using Reflection, you can create an instance of a class, call its methods, and access its properties dynamically at runtime.

The System.Reflection namespace contains classes that allow you to achieve reflection. So, make sure to add using System; and using System.Reflection; at the top of your .cs file.

What Is Metadata?

Metadata is information about types defined in an assembly. This information includes the type’s name, properties, methods, and events. The metadata can be accessed and manipulated using the Reflection API.
Metadata is an important aspect of C# Reflection. It allows developers to examine and manipulate a type’s properties and methods, making it possible to use those types more flexibly and dynamically.

Metadata contains information about the methods, properties, variables, etc. declared inside of an assembly.

C# Type Class

The C# Type class represents a type in the .NET Framework. It provides methods and properties that allow you to examine and manipulate the properties and methods of a type at runtime.
You can get information about the type’s name, namespace, base type, implemented interfaces, properties, methods, and events using the Type class.

Example : C# Reflection to get Assembly

The following code demonstrates how to use C# Reflection to get information about an assembly:

using System;
using System.Reflection;
class CSharp_Reflection
{
    public static void Main()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();

        Console.WriteLine("Assembly Name: {0}", assembly.FullName);
        Console.WriteLine("Location: {0}", assembly.Location);

        Type[] types = assembly.GetTypes();

        foreach (Type type in types)
        {
            Console.WriteLine("Type: {0}", type.Name);
        }
    }
}

Output:

CSharp_Reflection_Example

System.Reflection Namespace

Some of the most commonly used reflection namespace classes are:

  • Assembly: This class allows us to load, investigate and manipulate an assembly dynamically.
  • Module: Module class in reflection is used to discover information, such as the assembly containing the module and the classes in the module. You can also retrieve a list of all global methods and non-global methods specified in the module.
  • MethodInfo: This class is used to hold data about a method, such as its name, return type, parameters, access modifiers, and so on. To invoke a specific method, use the Type’s GetMethods() or GetMethod() method.
  • PropertyInfo: This class in reflection is used to contain information such as the name and data type of the property, and to get or set the value of the property.
  • FieldInfo: This class allows you to access field info. It is used to retrieve or update field values as well as discover information such as field names, access modifiers (such as public or private), and implementation details.
  • EventInfo: This class holds information such as the name, event-handler data type, custom attributes, etc. for a given event. Use this class to inspect events and bind to event handlers.
  • ConstructorInfo: This class is used to discover information such as the name, parameters, access modifiers, and implementation details of a constructor. Use the GetConstructors() or GetConstructor() method of Type to call a specific constructor.
  • CustomAttributeData: This class is used to get information on custom attributes or to examine attributes without having to create instances of them.

Reflection Example 2:

In the below code snippet, The typeof method is used to load the type t as an int. Then we use reflection on t to find information about the int type, such as its Name, FullName, Namespace, and BaseType.

// C# program to demonstrate the use of Reflection
using System;
using System.Reflection;
namespace Reflection_Example
{
    class Program
    {     
        static void Main(string[] args)
        {
            // Initialize t as typeof int
            Type t = typeof(int);

            // Use Reflection to retrieve the information related to type t
            Console.WriteLine($" Name : {t.Name}");
            Console.WriteLine($" Full Name : { t.FullName}");
            Console.WriteLine($" Namespace : {t.Namespace}");
            Console.WriteLine($" Base Type : {t.BaseType}");
            Console.ReadLine();
        }
    }
}

Following is the output of the above program.

reflection example in CSharp

Example 3:

static void Main(string[] args)
        {
            // Using Reflection to get information of an Assembly:
            Assembly info = typeof(int).Assembly;
            Console.WriteLine(info);
            Console.ReadLine();

            // Output:
            // mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
        }

Example 4: C# Reflection with String

The following code demonstrates how to use C# Reflection with a string:

string str = "Hello, World!";

Type stringType = str.GetType();

MethodInfo toUpperMethod = stringType.GetMethod("ToUpper", new Type[] { });

string upperCaseString = toUpperMethod.Invoke(str, null) as string;

Console.WriteLine(upperCaseString);

Output:

HELLO, WORLD!

Example 5: C# Reflection with Enumerable

The following code demonstrates how to use C# Reflection with Enumerable:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
class CSharp_Reflection
{
    public static void Main()
    {
        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.Add(3);

        IEnumerable enumerable = list as IEnumerable;

        Type enumerableType = enumerable.GetType();
        MethodInfo enumeratorMethod = enumerableType.GetMethod("GetEnumerator");
        IEnumerator enumerator = enumeratorMethod.Invoke(enumerable, null) as IEnumerator;

        while (enumerator.MoveNext())
        {
            Console.WriteLine("Value: {0}", enumerator.Current);
        }
    }
}

Output:

Value: 1
Value: 2
Value: 3

When to Use Reflection in C#?

Reflection is a powerful feature of C#, and we should use it carefully. Here are some scenarios where Reflection can be useful:

  • Reflection in C# can be used when you need to dynamically load an assembly at runtime.
  • It can be used to create an instance of a class whose type is not known at compile time.
  • It can be used to access private members of a class.
  • It can be used to examine or manipulate the properties and methods of a type at runtime.
  • Reflection in C# can be used for instantiating types in an assembly at the runtime by using the Activator.CreateInstance method.
  • If you want information about attributes on a type or method, you can use Reflection.
  • Reflection can be used to create a shared assembly.
  • Reflection can be used to solve the DLL hell problem by creating shared assemblies.
  • Reflection eases the process of deployment as we can do versioning of an assembly using Reflection (Example: [assembly: AssemblyVersion(“1.0.0.0”)]).

Dynamic Assembly Loading Using Reflection In C#

Let’s write a C# program to create a private assembly and load that assembly at runtime by using reflection.

Write the following program in notepad or Visual Studio editor and save the file as ‘User.cs’ in the local folder( Example D:\User\User.cs).

using System;
namespace Reflection
{
    // Class
    public class User
    {
        // field
        public int userId = 52894;

        //Method
        public string GetName()
        {
            return "Mr. Shekh Ali";
        }

        //Method
        public string Print(string message)
        {
            return message;
        }
    }
}

Open Visual Studio command prompt and execute the following command.
csc /t:library User.cs

Command to generate assembly using reflection in C#
Command to generate a private assembly.

A new assembly ‘User.dll’ is created in the ‘D:/User/’ drive.

Create Private Assembly Using Reflection in c#
A private assembly is created after executing the above command.

Now create a new console application, and write the following program to load the assembly at the runtime using the reflection.

Example 3:

Retrieving metadata of any assembly at runtime

In the following example, the MethodInfo and FieldInfo objects of the System.Reflection class must be initialized to discover the attributes of the method and field associated with the class.

//    Load the assembly at runtime using reflection in C#. 
using System;
using System.Reflection;
namespace Reflection
{
    class Program
    {
        static void Main(string[] args)
        {
         // Dynamically load assembly from file User.dll
          Assembly assembly = Assembly.LoadFile(@"D:\User\User.dll");

         // Get type of class 'User' from the loaded assembly  
          Type type = assembly.GetType("Reflection.User");

         // Create instance of 'User' class
          object instance = Activator.CreateInstance(type);

         // Call method: public string GetName()
          MethodInfo method = type.GetMethod("GetName");

        // Invoke method: 
           string name = Convert.ToString(method.Invoke(instance, null));
         //Call public field
          FieldInfo field = type.GetField("userId");
          int userId = (int)field.GetValue(instance);

          Console.WriteLine(userId);
          Console.WriteLine(name);         
          Console.ReadLine();

        }
    }
}


image Output of Reflection program
The output of the above program.

In the above program, we are calling field and method data from the assembly at runtime.

Access private method using reflection in C#

In C#, calling private methods from one class to another is technically impossible.
However, using reflection can call private methods from one class to another. Below is a C# program where we created a user class with private methods.
Here, we will call the private method of the User class the Main () method of the Program class.

Example 4: Invoking the private method using reflection

using System;
using System.Reflection;
namespace Reflection
{
    class User
    {
        // private method
        private string PrivateMethod()
        {
            return "Private method executed !!";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
          // Create object of User class
           User instance = new User();
         // Get type of User class 
          Type type = typeof(User);

         // Call private method with required binding constraints. 
          MethodInfo method = type.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);

        // Invoke method at the runtime 
           string name = Convert.ToString(method.Invoke(instance, null));
        
          Console.WriteLine(name);         
          Console.ReadLine();
        }
        //Output: Private method executed !!
    }
}
Calling private method using Reflection in c#
The output of the above C# program

In the example above, we used reflection to access the private methods of the class. Reflection in C# is often used in user interface applications such as ASP.NET. We can directly set the properties of TextBox, Button, ComboBox, and other controls.

To read more about reflection, please visit this MSDN link.

Conclusion:

In this post, I tried to cover most of the important functionality related to .NET reflection. I hope you found this post useful about Reflection. If so, please share it with others. Your suggestions, comments, and constructive criticism are greatly appreciated.

FAQ

Q: Is using reflection in C# a good practice?

Ans: It is generally not recommended to use reflection in application code because it eliminates strict type-checking.

Q: What is reflection used for in C#?

Ans: Reflection provides metadata at runtime that describes assemblies, modules, and types. You can use reflection to create an instance of a type dynamically and to invoke its methods, fields, and properties.

Q: How to load an assembly at runtime using reflection in C#?

Ans: The Assembly.LoadFile() method is used to load an assembly at runtime.

Q: What is Reflection in C#?

Reflection is a feature in C# that allows you to inspect and manipulate metadata, types, and objects during runtime.

Q: When should I use Reflection in C#?

Reflection can be helpful when you need to load an assembly at runtime dynamically, create an instance of a class whose type is not known at compile time, access private members of a class, or examine or manipulate the properties and methods of a type at runtime.

Q: What is Metadata in C#?

Metadata is information about types defined in an assembly. This information includes the type’s name, properties, methods, and events.

Recommended Articles:

Shekh Ali
0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments