Reflection · How it works

1 min read
Senior14 min read
Rapid overview

How it works

"Reflection lets your program look in the mirror: it can discover its own types, read metadata, and invoke members it has never seen at compile time."

Use this guide to master System.Reflection for interviews. Every section follows the Q&A format interviewers use, with working C# code examples, performance trade-offs, and real-world patterns.


MethodInfo, PropertyInfo, FieldInfo, ConstructorInfo Deep Dive

Q: What metadata can you extract from a MethodInfo?

A: MethodInfo exposes the method's name, return type, visibility, parameters, and more:

MethodInfo? method = typeof(string).GetMethod(
    "Contains", new[] { typeof(string) });

Console.WriteLine(method?.Name);            // Contains
Console.WriteLine(method?.ReturnType.Name); // Boolean
Console.WriteLine(method?.IsPublic);        // True
Console.WriteLine(method?.IsStatic);        // False
Console.WriteLine(method?.IsVirtual);       // True

// Parameter inspection
ParameterInfo[] parameters = method?.GetParameters() ?? Array.Empty<ParameterInfo>();
foreach (var p in parameters)
{
    Console.WriteLine($"  {p.Name}: {p.ParameterType.Name} (position {p.Position})");
}
// Output: value: String (position 0)
Q: What metadata can you extract from a PropertyInfo?

A: You can determine the property type, whether it has getters/setters, and the underlying accessor method names:

PropertyInfo prop = typeof(Trade).GetProperty("Price")!;

Console.WriteLine(prop.PropertyType.Name);  // Decimal
Console.WriteLine(prop.CanRead);            // True
Console.WriteLine(prop.CanWrite);           // True
Console.WriteLine(prop.GetMethod?.Name);    // get_Price
Console.WriteLine(prop.SetMethod?.Name);    // set_Price

// Init-only properties: SetMethod exists but calling SetValue
// after construction may throw in some scenarios.
Q: What metadata can you extract from a FieldInfo?

A: You can determine the field type, whether it is static, const, or readonly:

FieldInfo field = typeof(int).GetField("MaxValue")!;

Console.WriteLine(field.FieldType.Name); // Int32
Console.WriteLine(field.IsStatic);       // True
Console.WriteLine(field.IsLiteral);      // True (it's a const)
Console.WriteLine(field.IsInitOnly);     // False (const, not readonly)
Console.WriteLine(field.GetValue(null)); // 2147483647
Q: How do DI containers use ConstructorInfo to wire dependencies?

A: They inspect constructors to determine required dependencies, then resolve each parameter recursively:

public class OrderProcessor
{
    private readonly ILogger _logger;
    private readonly IOrderRepository _repo;

    public OrderProcessor(ILogger logger, IOrderRepository repo)
    {
        _logger = logger;
        _repo = repo;
    }
}

ConstructorInfo[] ctors = typeof(OrderProcessor).GetConstructors();
foreach (var ctor in ctors)
{
    var parms = ctor.GetParameters();
    Console.WriteLine($"Ctor with {parms.Length} params:");
    foreach (var p in parms)
        Console.WriteLine($"  {p.ParameterType.Name} {p.Name}");
}

// Create instance via ConstructorInfo
// (DI containers use patterns very similar to this)
ConstructorInfo ci = ctors[0];
object instance = ci.Invoke(new object[] { logger, repo });

See also