Question

Get a Property Value from a String Using Reflection in C#

csharpreflectionproperties

Question

I am trying to implement a data transformation approach similar to a reflection-based example in my code.

I currently have a GetSourceValue function that uses a switch statement to compare different types and properties. I want to remove those hard-coded types and property checks, and instead have GetSourceValue retrieve the value of a property using only a single string parameter.

The idea is to pass something like a class name and property name in a string, then resolve and return the value of that property dynamically.

Is this possible in C# using reflection?

Short Answer

By the end of this page, you will understand how to use reflection in C# to look up a property by name and read its value dynamically. You will also learn the difference between getting a property from an object instance versus from a type name string, how to handle nested property paths, and how to avoid common reflection mistakes.

Concept

Reflection in C# lets your program inspect types, properties, methods, and fields at runtime.

In this question, the core idea is: instead of writing code like this:

switch (propertyName)
{
    case "FirstName":
        return person.FirstName;
    case "Age":
        return person.Age;
}

you want to do something more dynamic:

return GetPropertyValue(person, "FirstName");

That is exactly the kind of problem reflection can solve.

Why this matters

Reflection is useful when:

  • property names are only known at runtime
  • you are building mapping or transformation tools
  • you are writing generic utilities
  • you want to reduce repetitive switch or if logic

The important distinction

There are two related but different problems:

  1. Get a property value from an object using a property name string

    • Example: given a Person object and the string "FirstName", return person.FirstName
  2. Get a type and property from strings

    • Example: given "MyApp.Models.Person" and "FirstName", locate the type and then read the property value from an instance

The first is common and practical. The second is possible too, but you still usually need an actual object instance to read a non-static property value.

Key rule

Reflection can find a property from a string, but:

  • for instance properties, you need an object instance
  • for static properties, you can read the value without an instance

So if you want to pass "Person.FirstName", reflection can identify the property, but it cannot magically know which Person object you mean unless you also provide the object instance.

Mental Model

Think of an object as a cabinet, and its properties as labeled drawers.

Normally, in C#, you open a drawer directly:

person.FirstName

That means you already know the drawer name at compile time.

Reflection is like saying:

“I have the cabinet, and I have the drawer label as text. Please find that drawer and open it.”

If you only have the text "FirstName", reflection can search the cabinet for a drawer with that label.

If you only have "Person.FirstName", that tells you the kind of cabinet and the drawer name, but not which exact cabinet instance you should open. That is why instance properties still require an object.

Take Quiz

Syntax and Examples

Basic syntax

To get a property value by name from an object:

using System;
using System.Reflection;

public static object? GetPropertyValue(object source, string propertyName)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentException("Property name is required.", nameof(propertyName));

    PropertyInfo? property = source.GetType().GetProperty(propertyName);

    if (property == null)
        throw new ArgumentException($"Property '{propertyName}' was not found on type '{source.GetType().Name}'.");

    return property.GetValue(source);
}

Example

using System;

public class Person
{
    public string FirstName { get; set; } = "Alice";
    public int Age { get; set; } = 30;
}

public class Program
{
    public static object? GetPropertyValue(object source, string propertyName)
    {
        var property = source.GetType().GetProperty(propertyName);
        return property?.GetValue(source);
    }

    public static void Main()
    {
        Person person = new Person();

        Console.WriteLine(GetPropertyValue(person, "FirstName"));
        Console.WriteLine(GetPropertyValue(person, "Age"));
    }
}

Output:

Alice
30

Using a full type name string

If you also have a type name as a string:

using System;
using System.Reflection;

public static object? GetStaticPropertyValue(string typeName, string propertyName)
{
    Type? type = Type.GetType(typeName);
    if (type == null)
        throw new ArgumentException($"Type '{typeName}' was not found.");

    PropertyInfo? property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Static);
    if (property == null)
        throw new ArgumentException($"Static property '{propertyName}' was not found on type '{type.Name}'.");

    return property.GetValue(null);
}

This only works directly for static properties. For normal instance properties, you still need an object.

Nested property paths

Sometimes you want a path like "Address.City".

using System;
using System.Reflection;

public static object? GetNestedPropertyValue(object source, string propertyPath)
{
    object? current = source;

    foreach (string part in propertyPath.Split('.'))
    {
        if (current == null) return null;

        PropertyInfo? property = current.GetType().GetProperty(part);
        if (property == null)
            throw new ArgumentException($"Property '{part}' was not found on type '{current.GetType().Name}'.");

        current = property.GetValue(current);
    }

    return current;
}

Example:

public class Address
{
    public string City { get; set; } = "London";
}

public class Person
{
    public string FirstName { get; set; } = "Alice";
    public Address Address { get; set; } = new Address();
}

Person person = new Person();
Console.WriteLine(GetNestedPropertyValue(person, "Address.City"));

Output:

London

Why this is useful

This lets you write reusable code for:

  • object mapping
  • export tools
  • generic reporting
  • data transformation pipelines

Step by Step Execution

Consider this code:

public class Person
{
    public string FirstName { get; set; } = "Alice";
}

Person person = new Person();
object? value = GetPropertyValue(person, "FirstName");
Console.WriteLine(value);

And this method:

public static object? GetPropertyValue(object source, string propertyName)
{
    PropertyInfo? property = source.GetType().GetProperty(propertyName);
    return property?.GetValue(source);
}

What happens step by step

  1. person is created as an instance of Person.
  2. GetPropertyValue(person, "FirstName") is called.
  3. source.GetType() returns the runtime type: Person.
  4. .GetProperty("FirstName") searches the Person type for a public property named FirstName.
  5. Reflection returns a PropertyInfo object representing that property.
  6. property.GetValue(source) reads the value of FirstName from the person object.
  7. The method returns "Alice" as an object.
  8. Console.WriteLine(value) prints Alice.

Trace example with nested properties

Person person = new Person
{
    FirstName = "Alice",
    Address = new Address { City = "Paris" }
};

object? value = GetNestedPropertyValue(person, "Address.City");

Execution flow:

  1. Start with current = person
  2. Split "Address.City" into "Address" and "City"
  3. Find property Address on Person
  4. Read person.Address
  5. Now current becomes the Address object
  6. Find property City on Address
  7. Read address.City
  8. Return "Paris"

This is how reflection can walk through an object structure dynamically.

Real World Use Cases

Data transformation and mapping

If you are converting one object into another, reflection can read source properties based on configuration strings.

Example:

  • source field: "Customer.Name"
  • destination field: "ClientName"

CSV or Excel export tools

A report generator can accept a list of property names and extract values without hard-coded access.

Example:

var columns = new[] { "FirstName", "Age" };

Admin dashboards

Generic UI components often display selected object properties dynamically.

Rule engines and configuration-driven systems

A config file may specify which property to inspect:

  • Order.Total
  • User.Email
  • Product.Price

Logging and auditing

Reflection can help collect certain values from objects for diagnostics or change tracking.

API response shaping

Some systems return only fields requested by the client. Reflection can be used to extract those properties, though this should be done carefully for performance and security.

Take Quiz

Real Codebase Usage

In real projects, developers often use reflection in controlled utility methods, not scattered everywhere.

Common pattern: reusable helper

public static object? GetPropertyValue(object source, string propertyName)
{
    if (source == null) return null;

    var property = source.GetType().GetProperty(propertyName);
    return property?.GetValue(source);
}

This keeps reflection logic in one place.

Guard clauses

Developers usually validate inputs early:

  • null object
  • empty property name
  • property not found
  • wrong casing

Configuration-driven mapping

A common pattern is storing property paths in configuration:

var mappings = new Dictionary<string, string>
{
    ["CustomerName"] = "Customer.Name",
    ["CustomerCity"] = "Customer.Address.City"
};

Then a mapper reads each path dynamically.

Error handling

Reflection code often fails at runtime if the property name is wrong. Real code usually:

  • throws clear exceptions
  • logs invalid property paths
  • returns null when appropriate
  • validates mappings at startup

Caching reflection metadata

Reflection is slower than direct property access. In real codebases, developers may cache PropertyInfo objects if the same properties are read repeatedly.

Safer alternatives when possible

If the set of properties is known, developers often prefer:

  • normal property access
  • delegates
  • expressions
  • mapping libraries

Reflection is usually chosen when flexibility is more important than compile-time safety.

Common Mistakes

1. Forgetting that instance properties need an object

Broken idea:

Type type = Type.GetType("MyApp.Person");
var property = type.GetProperty("FirstName");
var value = property.GetValue(null);

This fails for a normal instance property because null is only valid for static properties.

Fix:

Person person = new Person { FirstName = "Alice" };
var value = person.GetType().GetProperty("FirstName")?.GetValue(person);

2. Assuming Type.GetType always finds your class

Broken code:

Type type = Type.GetType("Person");

This often returns null unless the fully qualified type name is available.

Fix:

  • use the full namespace-qualified name
  • or use someObject.GetType() when you already have an instance

3. Not checking for missing properties

Broken code:

var property = source.GetType().GetProperty(propertyName);
return property.GetValue(source);

If the property does not exist, this throws a NullReferenceException.

Fix:

var property = source.GetType().GetProperty(propertyName);
if (property == null)
    throw new ArgumentException($"Property '{propertyName}' not found.");

return property.GetValue(source);

4. Ignoring case sensitivity

GetProperty("firstname") will not match FirstName by default.

Possible fix:

var property = source.GetType().GetProperty(
    propertyName,
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

Use this only if case-insensitive matching is acceptable.

5. Forgetting about null in nested paths

Broken code:

GetNestedPropertyValue(person, "Address.City")

If person.Address is null, the next lookup fails.

Fix:

  • return null when an intermediate object is null
  • or throw a clear exception

6. Overusing reflection

Reflection is powerful, but direct property access is:

  • faster
  • easier to read
  • compile-time checked

Use reflection when you truly need runtime flexibility.

Comparisons

Reflection vs hard-coded property access

ApproachExampleProsCons
Hard-coded accessperson.FirstNameFast, safe, easy to refactorNot dynamic
ReflectionGetPropertyValue(person, "FirstName")Flexible, config-drivenSlower, runtime errors possible

Reflection vs switch statement

ApproachBest whenProsCons
switchsmall fixed list of propertiessimple, explicitrepetitive, harder to extend
Reflectionproperty names come from config or inputgeneric, reusableless compile-time safety

Instance property vs static property

Property typeNeeds object instance?Example access
Instance propertyYesproperty.GetValue(person)
Static propertyNoproperty.GetValue(null)

Reflection vs expressions/delegates

ApproachProsCons
ReflectionWorks from stringsweaker typing
Delegate / lambdafast and type-safecannot be built from a plain property string without extra work

If you already know the property at compile time, a lambda is usually better. If the property name is only known at runtime, reflection is often the simplest option.

Take Quiz

Cheat Sheet

Quick reference

Get property from object by name

var property = source.GetType().GetProperty("FirstName");
var value = property?.GetValue(source);

Safe helper

public static object? GetPropertyValue(object source, string propertyName)
{
    if (source == null) throw new ArgumentNullException(nameof(source));

    var property = source.GetType().GetProperty(propertyName);
    if (property == null)
        throw new ArgumentException($"Property '{propertyName}' not found.");

    return property.GetValue(source);
}

Case-insensitive lookup

var property = source.GetType().GetProperty(
    propertyName,
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

Nested property path

"Address.City"

Loop through each part and call GetProperty() repeatedly.

Static property lookup

var property = type.GetProperty("SomeStaticProperty", BindingFlags.Public | BindingFlags.Static);
var value = property?.GetValue(null);

Important rules

  • Instance properties require an object instance.
  • Static properties can use null in GetValue.
  • GetProperty() may return null.
  • Reflection errors happen at runtime, not compile time.
  • Reflection is slower than direct access.

Common edge cases

  • wrong property name
  • wrong letter casing
  • null intermediate object in nested paths
  • Type.GetType() returning null
  • non-public properties needing extra binding flags

FAQ

Can I get a property value from just a string in C#?

Yes, if the string is the property name and you also have the object instance. Reflection can then find and read that property.

Can I pass "ClassName.PropertyName" and get the value directly?

Only if you can also identify the object instance for that class, unless the property is static.

Why does Type.GetType() return null?

Usually because the type name is incomplete. You often need the fully qualified type name, including namespace.

Does reflection work with private properties?

Yes, but you need different binding flags. For most beginner use cases, public properties are simpler and safer.

Is reflection slow?

It is slower than direct property access, but often acceptable for occasional lookups. For heavy repeated use, consider caching.

How do I read nested properties like Address.City?

Split the string by . and resolve each property one step at a time.

What should I return if the property does not exist?

That depends on your design. Common options are returning null, throwing an exception, or logging an error.

Should I replace all switch statements with reflection?

No. Reflection is best when property names are dynamic. If the set of cases is fixed and small, a switch is often clearer.

Take Quiz

Mini Project

Description

Build a small reflection-based property reader for a data export tool. Imagine you have objects such as Person and want to export selected fields based on configuration strings like "FirstName" or "Address.City". This project demonstrates how to dynamically resolve property paths instead of hard-coding every property access.

Goal

Create a utility that reads both simple and nested property values from an object using a string path.

Requirements

  1. Create a Person class with at least FirstName, Age, and Address properties.
  2. Create an Address class with at least a City property.
  3. Write a method that accepts an object and a property path string such as "FirstName" or "Address.City".
  4. Return the correct property value using reflection.
  5. Handle missing properties with a clear exception or a null result.
Take Quiz

Keep learning

Related questions

View more