Reflection Overview
2 min readReflection Overview
TL;DR
🔍 Interview Angle: Be ready to explain how ActivatorUtilities or JsonSerializer leverage reflection and how source generators reduce reflection cost in .NET 5+.
How it works
- Concept: Inspect metadata and interact with types at runtime via
System.Reflection. - Use Cases: Plugin discovery, serialization, mapping attributes to behavior, building DI containers.
- Cost: Reflection is slower—cache
PropertyInfo/MethodInfoor emit delegates (CreateDelegate) for hot paths.
var assembly = Assembly.Load("Trading.Services");
var handlers = assembly.GetTypes()
.Where(t => typeof(ICommandHandler).IsAssignableFrom(t) && !t.IsAbstract);
foreach (var handler in handlers)
{
Console.WriteLine($"Discovered handler: {handler.Name}");
}
Quick recall Q&A
For dynamic scenarios like plugin discovery, serialization, attribute-driven behavior, or tooling where compile-time knowledge is limited. Use it outside hot paths or cache results.
Cache PropertyInfo/MethodInfo, create delegates via CreateDelegate, or use Expression trees to generate accessors. Source generators can precompute metadata to avoid runtime reflection entirely.
Compile-time registration, source generators, or manual wiring. Reflection simplifies auto-discovery but can slow startup; balance convenience with performance.
Trimming can remove unused members. Reflection needs preserved metadata, so mark types with DynamicallyAccessedMembers or Preserve attributes when building self-contained apps.
Validate assembly paths, restrict loaded types/namespaces, and avoid executing untrusted code. Reflection can bypass encapsulation, so enforce security at the host/application level.
Yes via BindingFlags.NonPublic, but it should be used sparingly (e.g., for testing). It can break encapsulation and may fail under IL trimming.
System.Reflection.Emit?To generate types/methods at runtime (dynamic proxies, serialization). It’s powerful but complex; prefer Expression trees or source generators when possible.
Activator.CreateInstance vs new?Activator.CreateInstance is slower because it uses reflection. Cache constructors via compiled delegates when instantiating frequently.
JsonSerializer leverage reflection?It inspects types at runtime to discover properties/attributes. In .NET 6+, source generators can precompute serializers to avoid reflection overhead and enable trimming.
Write unit tests for discovery logic (ensuring correct types are found) and integration tests that verify attributes/config drive expected behavior. Mock metadata where possible.