| Generics in C# | Attributes in C# | |
🔍 Reflection in C# |
Reflection in C# is the ability of a program to inspect and manipulate its own metadata during runtime. It allows you to obtain information about types (classes, interfaces, structs), members (properties, methods, fields), and assemblies. Reflection is a powerful feature that enables dynamic and flexible programming, but it should be used judiciously due to performance overhead.
The central class for using reflection is System.Type. You can get an instance of Type in several ways:
Type type = typeof(string);
Use code with caution.
string myString = "hello"; Type type = myString.GetType();
Use code with caution.
Type? type = Type.GetType("System.String");
Use code with caution.
Once you have a Type object, you can access all the metadata associated with it.
This example shows how to get information about a class, including its properties and methods.
using System;
using System.Reflection;
public class MyClass
{
public int MyProperty { get; set; }
public void MyMethod(string message)
{
Console.WriteLine($"Method called with message: {message}");
}
}
public class ReflectionExample
{
public static void Main()
{
Type myType = typeof(MyClass);
Console.WriteLine($"Type Name: {myType.Name}");
Console.WriteLine($"Full Name: {myType.FullName}");
Console.WriteLine("\n--- Properties ---");
foreach (PropertyInfo property in myType.GetProperties())
{
Console.WriteLine($"Property Name: {property.Name}");
}
Console.WriteLine("\n--- Methods ---");
foreach (MethodInfo method in myType.GetMethods())
{
if (method.DeclaringType == myType)
{
Console.WriteLine($"Method Name: {method.Name}");
}
}
}
}
Use code with caution.
Output:
Type Name: MyClass Full Name: MyClass --- Properties --- Property Name: MyProperty --- Methods --- Method Name: MyMethod
This is known as late binding, where you do not know the type at compile time. The following example shows how to create an instance and call a method using strings.
using System;
using System.Reflection;
public class Greeter
{
public void SayHello(string name)
{
Console.WriteLine($"Hello, {name}!");
}
}
public class DynamicInvocationExample
{
public static void Main()
{
Type? greeterType = Type.GetType("Greeter");
if (greeterType != null)
{
object? greeterInstance = Activator.CreateInstance(greeterType);
MethodInfo? sayHelloMethod = greeterType.GetMethod("SayHello");
if (greeterInstance != null && sayHelloMethod != null)
{
sayHelloMethod.Invoke(greeterInstance, new object[] { "Reflection" });
}
}
}
}
Use code with caution.
Output:
Hello, Reflection!
| Advantage | Disadvantage |
|---|---|
| Enables extensibility: Build plugin-based architectures by loading assemblies at runtime. | Performance overhead: Reflection is slower than direct method calls due to runtime type resolution. |
| Late binding: Allows calling members not known at compile time. | Breaks strong typing: May cause runtime errors if the member doesn’t exist or is incompatible. |
| Inspects metadata: Useful for reading custom attributes, e.g., in serializers or ORMs. | Exposes internals: Can bypass access modifiers, breaking encapsulation. |
| Facilitates unit testing: Reflection identifies test methods via attributes. | Hard to maintain: Code using reflection is harder to read and debug. |
Reflection is powerful but should be used only when compile-time mechanisms are insufficient. Common use cases include:
Reflection is a powerful feature in C# that allows you to inspect and interact with metadata about assemblies, types, and members at runtime. It’s part of the System.Reflection namespace and is widely used in dynamic programming, testing, and tooling.
using System;
using System.Reflection;
public class Student {
public string Name { get; set; }
public int Age { get; set; }
public void DisplayInfo() {
Console.WriteLine($"Name: {Name}, Age: {Age}");
}
}
class Program {
static void Main() {
Type type = typeof(Student);
Console.WriteLine("Properties:");
foreach (var prop in type.GetProperties()) {
Console.WriteLine(prop.Name);
}
Console.WriteLine("\nMethods:");
foreach (var method in type.GetMethods()) {
Console.WriteLine(method.Name);
}
}
}
Type.GetProperties() – Gets all public properties.Type.GetFields() – Gets all fields.Type.GetMethods() – Gets all methods.Assembly.Load() – Loads an assembly dynamically.Activator.CreateInstance() – Creates an object dynamically.MethodInfo.Invoke() – Invokes a method at runtime.BindingFlags to control visibility (public/private/static).MissingMethodException or TargetInvocationException.Reflection in C# is a powerful tool for dynamic programming and runtime inspection. While it offers great flexibility, it should be used judiciously to avoid performance and maintainability issues. Mastering reflection unlocks advanced capabilities in tooling, testing, and extensibility.
| Generics in C# | Attributes in C# | |