Reflection in C#

Reflection is a powerful feature in C# that allows you to inspect and manipulate the metadata of types, objects, and assemblies at runtime. Reflection provides a way to dynamically query and modify the structure and behavior of objects without necessarily having to know their types at compile time.

In C#, reflection is performed using the `System.Reflection` namespace, which contains classes and methods for working with metadata. The most commonly used classes are `Type`, `MethodInfo`, and `PropertyInfo`.

Here’s an example of using reflection to inspect the properties of an object:

class MyClass
{
    public int MyProperty { get; set; }
}

MyClass obj = new MyClass();
Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties();

foreach (PropertyInfo property in properties)
{
    Console.WriteLine(property.Name);
}

In this example, the `GetType` method is used to get the type of the `obj` object. The `GetProperties` method is then used to get an array of `PropertyInfo` objects that represent the properties of the object. These `PropertyInfo` objects can be used to inspect and modify the properties of the object at runtime.

Reflection can also be used to create new instances of types, invoke methods dynamically, and access private members of objects. Here’s an example of using reflection to create a new instance of a type and invoke a method on it:

Type type = typeof(MyClass);
object obj = Activator.CreateInstance(type);
MethodInfomethod = type.GetMethod("MyMethod");
method.Invoke(obj, null);

In this example, the `typeof` operator is used to get the type of `MyClass`. The `Activator.CreateInstance` method is then used to create a new instance of the type. The `GetMethod` method is used to get a `MethodInfo` object that represents the `MyMethod` method of the type. Finally, the `Invoke` method is used to invoke the method on the object.

Reflection is a powerful feature in C# that allows you to dynamically inspect and manipulate the metadata of types, objects, and assemblies at runtime. By using reflection, you can write code that is more flexible, reusable, and extensible. However, reflection can also have performance implications and should be used judiciously.