Advanced C# Features: Reflection
Quick Answer
Reflection in C# allows programs to inspect and manipulate object types, methods, and properties at runtime. It is essential for dynamic type discovery, late binding, and building flexible applications such as serializers, dependency injectors, and testing frameworks.
Learning Objectives
- Explain the purpose of Reflection in a practical learning context.
- Identify the main ideas, terms, and decisions involved in Reflection.
- Apply Reflection in a simple real-world scenario or practice task.
Introduction to Reflection in C#
Reflection is a powerful feature in C# that enables programs to inspect metadata about assemblies, types, and members at runtime.
It allows developers to dynamically create instances, invoke methods, and access fields or properties without knowing them at compile time.
Reflection provides the ability to inspect and interact with code metadata at runtime.
What is Reflection?
Reflection is the process by which a program can examine and modify its own structure and behavior during execution.
In C#, this is primarily done through the System.Reflection namespace, which provides classes to access metadata about assemblies, modules, types, and members.
- Inspect assemblies and types at runtime
- Create objects dynamically
- Invoke methods and access fields or properties
- Discover attributes applied to code elements
Core Reflection Classes
Several key classes in System.Reflection enable reflection operations in C#.
Understanding these classes is essential to effectively use reflection.
- Assembly: Represents a loaded .NET assembly.
- Type: Represents type declarations including classes, interfaces, and enums.
- MethodInfo: Provides information about methods and allows invocation.
- PropertyInfo: Represents properties and allows getting/setting values.
- FieldInfo: Represents fields and allows access to their values.
- ConstructorInfo: Represents constructors and allows dynamic object creation.
Using Reflection to Inspect Types
You can obtain a Type object using the typeof operator or the GetType() method on an instance.
Once you have a Type, you can query its members such as methods, properties, and fields.
- Use Type.GetMethods() to list all methods.
- Use Type.GetProperties() to list all properties.
- Use Type.GetFields() to list all fields.
Example: Inspecting a Class
The following example demonstrates how to inspect the methods and properties of a class using reflection.
Invoking Methods Dynamically
Reflection allows you to invoke methods on objects dynamically without compile-time knowledge of the method.
This is useful for plugin architectures, scripting, or testing frameworks.
- Obtain MethodInfo from the Type.
- Use MethodInfo.Invoke() to call the method on an instance.
- Pass parameters as an object array.
Creating Objects at Runtime
You can create instances of types dynamically using reflection.
ConstructorInfo or Activator.CreateInstance can be used to instantiate objects.
- Use Activator.CreateInstance(Type) for parameterless constructors.
- Use ConstructorInfo.Invoke() for constructors with parameters.
Working with Attributes via Reflection
Attributes provide metadata about code elements.
Reflection can be used to read custom attributes applied to classes, methods, or properties.
- Use MemberInfo.GetCustomAttributes() to retrieve attributes.
- Check for specific attribute types using LINQ or filtering.
Performance Considerations
Reflection is powerful but can be slower than direct code execution.
Use it judiciously in performance-critical applications.
- Cache reflected metadata to avoid repeated lookups.
- Avoid excessive use in tight loops.
- Consider alternatives like expression trees or dynamic code generation if performance is critical.
Practical Example
This example uses reflection to list all public instance methods and properties declared in the Person class.
This example demonstrates how to invoke the Add method dynamically using reflection.
This example shows how to create an instance of the Animal class at runtime using Activator.CreateInstance.
Examples
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void SayHello() => Console.WriteLine($"Hello, my name is {Name}.");
}
class Program
{
static void Main()
{
Type personType = typeof(Person);
Console.WriteLine("Methods:");
foreach (MethodInfo method in personType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Console.WriteLine(method.Name);
}
Console.WriteLine("Properties:");
foreach (PropertyInfo prop in personType.GetProperties())
{
Console.WriteLine(prop.Name);
}
}
}This example uses reflection to list all public instance methods and properties declared in the Person class.
using System;
using System.Reflection;
public class Calculator
{
public int Add(int a, int b) => a + b;
}
class Program
{
static void Main()
{
Calculator calc = new Calculator();
MethodInfo addMethod = typeof(Calculator).GetMethod("Add");
object result = addMethod.Invoke(calc, new object[] { 5, 3 });
Console.WriteLine($"Result: {result}");
}
}This example demonstrates how to invoke the Add method dynamically using reflection.
using System;
public class Animal
{
public string Species { get; set; }
public Animal() { Species = "Unknown"; }
}
class Program
{
static void Main()
{
Type animalType = typeof(Animal);
object animalInstance = Activator.CreateInstance(animalType);
Console.WriteLine(((Animal)animalInstance).Species);
}
}This example shows how to create an instance of the Animal class at runtime using Activator.CreateInstance.
Best Practices
- Cache Type and MethodInfo objects to improve performance.
- Use BindingFlags to control visibility and scope when retrieving members.
- Validate inputs and handle exceptions when invoking methods dynamically.
- Limit reflection usage in performance-critical code paths.
- Use reflection primarily for scenarios requiring dynamic type handling.
Common Mistakes
- Ignoring performance impact of reflection in tight loops.
- Not specifying correct BindingFlags leading to missing members.
- Failing to handle exceptions from MethodInfo.Invoke properly.
- Assuming reflection can access private members without proper flags.
- Overusing reflection when static typing suffices.
Hands-on Exercise
Inspect a Custom Class Using Reflection
Create a class with several methods and properties. Write a program that uses reflection to list all public methods and properties of this class.
Expected output: A list of method and property names printed to the console.
Hint: Use typeof() to get the Type and then GetMethods() and GetProperties() with appropriate BindingFlags.
Invoke a Method Dynamically
Write a program that dynamically invokes a method with parameters on an object using reflection.
Expected output: The method's output or return value displayed correctly.
Hint: Use Type.GetMethod() to get MethodInfo and then MethodInfo.Invoke() to call the method.
Create an Object at Runtime
Use reflection to create an instance of a class with a parameterless constructor and access one of its properties.
Expected output: The property value printed to the console.
Hint: Use Activator.CreateInstance() and cast the object to the class type.
Interview Questions
What is Reflection in C# and when would you use it?
InterviewReflection is a feature that allows inspection and manipulation of types and members at runtime. It is used for dynamic type discovery, late binding, serialization, dependency injection, and building flexible frameworks.
How do you invoke a method dynamically using reflection?
InterviewYou obtain a MethodInfo object for the method and call its Invoke() method, passing the target instance and an array of parameters.
What are some performance considerations when using reflection?
InterviewReflection is slower than direct calls. To mitigate this, cache metadata objects, avoid reflection in tight loops, and consider alternatives like expression trees for performance-critical code.
MCQ Quiz
1. What is the best first step when learning Reflection?
A. Understand the purpose and basic idea
B. Skip directly to advanced implementation
C. Ignore examples and practice
D. Memorize terms without context
Correct answer: A
Starting with the purpose and basic idea makes later examples and practice easier to understand.
2. Which activity helps reinforce Reflection?
A. Reading once without practice
B. Building or writing a small practical example
C. Avoiding review questions
D. Skipping the summary
Correct answer: B
A small practical example helps connect the topic to real usage.
3. Which statement is most accurate about this topic?
A. Reflection in C# allows programs to inspect and manipulate object types, methods, and properties at runtime.
B. Reflection never needs examples
C. Reflection is unrelated to practical work
D. Reflection should be learned without checking results
Correct answer: A
The correct option is based on the available topic explanation.
Key Takeaways
- Reflection in C# allows programs to inspect and manipulate object types, methods, and properties at runtime.
- It is essential for dynamic type discovery, late binding, and building flexible applications such as serializers, dependency injectors, and testing frameworks.
- Reflection is a powerful feature in C# that enables programs to inspect metadata about assemblies, types, and members at runtime.
- It allows developers to dynamically create instances, invoke methods, and access fields or properties without knowing them at compile time.
- Reflection is the process by which a program can examine and modify its own structure and behavior during execution.
Summary
Reflection in C# is a versatile tool for inspecting and manipulating types and members at runtime.
It enables dynamic programming scenarios such as late binding, dynamic object creation, and attribute inspection.
While powerful, reflection should be used carefully due to its performance overhead and complexity.
Mastering reflection expands your ability to build flexible and extensible applications.
Frequently Asked Questions
Can reflection access private members?
Yes, reflection can access private members if you specify the appropriate BindingFlags, but it should be used cautiously as it breaks encapsulation.
Is reflection slow?
Reflection is generally slower than direct code execution because it involves metadata inspection and dynamic invocation, so it should be used judiciously.
What namespace contains reflection classes in C#?
The System.Reflection namespace contains the core classes for reflection in C#.
Can reflection be used to create instances of types?
Yes, reflection can create instances dynamically using Activator.CreateInstance or ConstructorInfo.Invoke.
What is Reflection?
Reflection in C# allows programs to inspect and manipulate object types, methods, and properties at runtime.
Why is Reflection important?
It is essential for dynamic type discovery, late binding, and building flexible applications such as serializers, dependency injectors, and testing frameworks.

