Zum Inhalt springen

Reflection in C# : What It Is, How It Works, and Why It Matters for Unity Developers

What is Reflection?

  • C# program compiles into an assembly that includes metadata, compiled code and resources. Inpsecting the metadata and compiled code at runtime is called reflection

To understand reflection properly , you need to understand what metadata is first.

What is metadata?

  • In C# , metadata refers to information about built-in or custom types, members and other constructs defined in an assembly.
  • In other words, metadata is not the data itself — it’s data about data.
  • It tells the runtime things like : What classes and interfaces exist, Which field, properties and methods they have, what attributes decorate them and more.

How It Works?

  • Let’s take a look at how to obtain a Type — the backbone of the Reflection API — inspect its metadata, and use it to interact with your code at runtime.

In C#, every object and type has metadata attached to it. The System.Type class represents this information. You can get a Type object in a few ways:

  1. Using typeof(T)
    Type type1 = typeof(Player)

  2. Using .GetType() on an instance
    Type type2 = (new Player()).GetType();

Once you have a Type , you can:

  • Inspect its fields, properties and methods
  • Check its attributes
  • Invoke methods or create instances dynamically

How to use it?

Okay that’s enough of theory let’s code a simple player class and inspect it’s properties , methods and attributes at runtime.

Player class

[Serializable]
public class Player
{
    public string Name { get; private set; }
    public int Level { get; private set; }

    public Player(string name, int level)
    {
        Name = name;
        Level = level;
    }

    // parameterless constructor
    public Player() { }

    public void LevelUp()
    {
        Level++;
        Debug.Log("Player leveled up");
    }
}

Reflector class

private void Start()
    {
        Player player = new Player("Dude", 1);

        // Get the Type metadata of Player
        Type playerType = player.GetType();

        // Get property value using Reflection
        var level = playerType.GetProperty("Level").GetValue(player);
        Debug.Log($"Level: {level}"); // Output: Level: 1

        // Inspect all properties
        PropertyInfo[] properties = playerType.GetProperties(
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        foreach (var property in properties)
        {
            Debug.Log($"Property Name: {property.Name}"); // Output: Name, Level
        }

        // Inspect and invoke methods with no parameters
        MethodInfo[] methods = playerType.GetMethods(
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        foreach (var methodInfo in methods)
        {
            if (methodInfo.GetParameters().Length == 0)
            {
                Debug.Log($"Invoking: {methodInfo.Name}");
                methodInfo.Invoke(player, null); 
                // Will call LevelUp and show "Player leveled up"
            }
        }

        // Inspect class-level attributes
        IEnumerable<Attribute> attributes = playerType.GetCustomAttributes();
        foreach (var attribute in attributes)
        {
            Debug.Log($"Player class has an attribute named: {attribute.GetType().Name}"); 
            // Output: Player class has an attribute named: SerializableAttribute
        }
    }

✨ And that’s it — now you’ve seen how Reflection works in C# and how you can use it in Unity to peek inside your own code!

It’s a handy tool for building smarter workflows, editor tools, or just satisfying your curiosity at runtime, but be careful about performance costs of it.

Stay tuned — in upcoming articles, we’ll build a simple yet extendable Developer Console using Reflection and Attributes.

✨ Thanks for reading!
buy me a coffee

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert