CodeGym /Courses /C# SELF /Using reflection

Using reflection

C# SELF
Level 63, Lesson 1
Available

1. Introduction

In C# any class (or struct) is a set of members. These include:

  • Fields (fields): variables that store data.
  • Properties (properties): “smart” wrappers with get/set.
  • Methods (methods): functionality.
  • Constructors (constructors): ways to create an instance.
  • Events (events): publish-subscribe done smartly.

Imagine you have a magic magnifier that lets you peek inside any type, see what's inside and even modify it. That's reflection.

Namespace and main reflection types

Before you start, don't forget to include the namespace:

using System.Reflection;

Key classes and interfaces:

Class/interface Description
Type
The main entry point — everything starts from it
FieldInfo
Information about a field
PropertyInfo
Information about a property
MethodInfo
Information about a method
ConstructorInfo
Information about a constructor
EventInfo
Information about an event
MemberInfo
Common “parent” for all the above

2. Getting type members via reflection

Getting fields and properties

Example: enumerating fields and properties

Suppose we have this class:

public class Person
{
    public string Name { get; set; }
    public int Age;
    private string Secret = "Secret word";
}

Getting fields:

Type personType = typeof(Person);

FieldInfo[] fields = personType.GetFields(
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

foreach (var field in fields)
{
    Console.WriteLine($"Field: {field.Name}, Type: {field.FieldType.Name}, Attributes: {field.Attributes}");
}

Getting properties:

PropertyInfo[] properties = personType.GetProperties(
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

foreach (var property in properties)
{
    Console.WriteLine($"Property: {property.Name}, Type: {property.PropertyType.Name}");
}

Notes

  • BindingFlags is a set of “flags” that tell which members to look for (public/private, instance/static, etc.).
  • Fields and properties differ: a field is a chunk of data, a property is get/set methods that hide a field.

Getting methods

MethodInfo[] methods = personType.GetMethods(
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

foreach (var method in methods)
{
    Console.WriteLine($"Method: {method.Name}");
}

You'll be surprised how many methods show up. There will be property getters/setters and helpers from object!

Useful filter: to get only your “explicit” methods, you can add filtering by name or attribute.

What to search with which BindingFlags

What to look for Example call Description
Public fields
GetFields(BindingFlags.Public | ...)
Everything visible to others
Private fields
GetFields(BindingFlags.NonPublic | ...)
Hidden internals
Instance only
BindingFlags.Instance
Only non-static
Static only
BindingFlags.Static
Only static
All at once
BindingFlags.Public | NonPublic | Instance | Static
Full list

3. Dynamically creating an instance of a type

Why is this cool?
You can create an object without knowing its exact type at compile time.

Simple way — via Activator.CreateInstance

// Get the Type somehow, for example:
Type myType = typeof(Person);
// Create the object:
object obj = Activator.CreateInstance(myType);
// Now obj is an instance of Person, but as object

If the class doesn't have a parameterless constructor, you can pass parameters:

public class Animal
{
    public string Name { get; }
    public Animal(string name) { Name = name; }
}

// ...
Type animalType = typeof(Animal);
object dog = Activator.CreateInstance(animalType, "Rex");

Important!

Console.WriteLine(dog.GetType().Name); // Animal

More custom way — via ConstructorInfo

ConstructorInfo ctor = animalType.GetConstructor(new Type[] { typeof(string) });
object dog = ctor.Invoke(new object[] { "Rex" });

In real life you usually use Activator, but sometimes you need exact control over parameters or to work with private constructors — that's where ConstructorInfo helps.

4. Accessing fields and properties by name

Get and change a field

Person p = new Person();
Type t = p.GetType();

FieldInfo field = t.GetField("Age");
field.SetValue(p, 42);
Console.WriteLine(field.GetValue(p)); // 42

Working with private fields:

FieldInfo secret = t.GetField("Secret", BindingFlags.NonPublic | BindingFlags.Instance);
if (secret != null)
{
    secret.SetValue(p, "Oh, secret is out");
    Console.WriteLine(secret.GetValue(p));
}
else
{
    Console.WriteLine("Field Secret not found");
}

Careful! Don't overuse access to private fields — it's breaking encapsulation and can cause bugs.

Get and change properties

PropertyInfo pi = t.GetProperty("Name");
pi.SetValue(p, "Bob");
Console.WriteLine(pi.GetValue(p)); // Bob

Properties are not fields, they're get/set methods under the hood.

Why sometimes it doesn't work?

If your field or property is private, be sure to add BindingFlags with the needed values (for example, NonPublic). If a property has no setter, you can't write to it via reflection — the rule still applies.

5. Invoking methods by name

Invoke a simple method without parameters

public class Greeter
{
    public void SayHello()
    {
        Console.WriteLine("Hello!");
    }
}

Greeter g = new Greeter();
Type t = g.GetType();
MethodInfo mi = t.GetMethod("SayHello");
mi.Invoke(g, null); // Hello!

Invoke a method with parameters

public class MathOp
{
    public int Add(int x, int y) => x + y;
}

MathOp calc = new MathOp();
Type t = calc.GetType();
MethodInfo mi = t.GetMethod("Add");
object result = mi.Invoke(calc, new object[] { 7, 5 });
Console.WriteLine(result); // 12

If the method is static, pass null as the first argument to Invoke.

Working with overloaded methods

MethodInfo mi = t.GetMethod(
    "Add", 
    new Type[] { typeof(int), typeof(int) }
);

Or iterate and filter manually:

foreach(var method in t.GetMethods()) {
    if (method.Name == "Add" && method.GetParameters().Length == 2) 
    {
        // ... our method!
    }
}

6. Useful nuances

Main members, methods and properties for type analysis

Class member Method to get info Result class How to read/change value
Field (field)
GetField, GetFields
FieldInfo
.GetValue(obj), .SetValue(obj, x)
Property (prop)
GetProperty, GetProperties
PropertyInfo
.GetValue(obj), .SetValue(obj, x)
Method (method)
GetMethod, GetMethods
MethodInfo
.Invoke(obj, parameters)
Constructor
GetConstructor, GetConstructors
ConstructorInfo
.Invoke(parameters)

Why this is useful in real life?

  • In ORM frameworks (for example, Entity Framework builds SQL queries from your models).
  • In serialization systems and parsers (for example, JSON serializers).
  • In general-purpose libraries for logging, testing, UI generators.
  • In interviews — they like to ask “how would you write a universal object copier?”.
  • For writing plugins, when your program loads and calls code written by others.

Even if it seems like hacker-movie magic now, trust me — it'll come in handy!

7. Typical mistakes and gotchas

Developers often get confused with BindingFlags — not seeing private fields or getting too many methods. Always check the combination of flags: for private fields use NonPublic, for static — Static, etc.

When calling methods via Invoke pass arguments in the same order and types as in the declaration. Wrong order/type will lead to TargetParameterCountException or ArgumentException. The return value arrives as object — don't forget to cast (or use pattern matching).

Don't forget about performance: reflection is slower than direct calls. Cache found Type/MethodInfo/PropertyInfo in hot paths or pre-generate delegates.

You will often see helper methods like get_PropertyName and set_PropertyName. These are property accessors — you don't need to create them manually.

If you change private fields or properties — you're breaking encapsulation. Misuse can lead to hard-to-find bugs. As Uncle Ben said: “With great power comes great responsibility” — use carefully, especially in library projects.

2
Task
C# SELF, level 63, lesson 1
Locked
Calling a Method via Reflection
Calling a Method via Reflection
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION