You can get a list of a type’s properties using reflection, like this:
foreach(var propertyInfo in typeof(Movie).GetProperties())
{
Console.WriteLine(propertyInfo.Name);
}
Code language: C# (cs)
Note: If you have an object, use movie.GetType().GetProperties() instead.
This outputs the following:
Id
Title
Director
ReleasedOn
BoxOfficeRevenue
Code language: plaintext (plaintext)
When you use GetProperties(), it returns a list of PropertyInfo objects. This gives you access the property’s definition (name, type, etc…) and allows you to get and modify its value.
In this article, I’ll show examples of using reflection to look for and use properties.
Table of Contents
Get and modify property values
You can use PropertyInfo.GetValue() / SetValue() to get and modify property values.
I’ll show examples of getting / modifying properties on the following Movie object:
var movie = new Movie()
{
Id = 10,
Title = "John Wick",
Director = "Chad Stahelski",
ReleasedOn = DateTime.Parse("2014/10/24"),
BoxOfficeRevenue = 86_000_000
};
Code language: C# (cs)
Get property values
Use PropertyInfo.GetValue() to get a property’s value.
This example is getting all properties and their values:
foreach (var propertyInfo in movie.GetType().GetProperties())
{
var propertyName = propertyInfo.Name;
var propertyValue = propertyInfo.GetValue(movie);
Console.WriteLine($"{propertyName}={propertyValue}");
}
Code language: C# (cs)
Note: Notice the difference between reflecting a type’s properties vs reflecting an object’s properties (typeof(movie).GetProperties() vs movie.GetType().GetProperties()).
This outputs the property names and values:
Id=10
Title=John Wick
Director=Chad Stahelski
ReleasedOn=10/24/2014 12:00:00 AM
BoxOfficeRevenue=86000000
Code language: plaintext (plaintext)
Modify property values
Use PropertyInfo.SetValue() to modify a property’s value.
This example is modifying the Movie.Director property value:
var directorProperty = movie.GetType().GetProperty("Director");
directorProperty.SetValue(movie, "Stahelski");
Console.WriteLine(movie.Director);
Code language: C# (cs)
This outputs the updated property value:
Stahelski
Code language: plaintext (plaintext)
Problems to avoid
There are a few things to watch out for when using PropertyInfo.SetValue() / GetValue(). I’ll show examples in the sections below.
Set the right type
Movie.Id is an integer, and this is trying to set its value to a string:
string id = "10";
var idProp = movie.GetType().GetProperty("Id");
idProp.SetValue(movie, id);
Code language: C# (cs)
This results in the following exception:
System.ArgumentException: Object of type ‘System.String’ cannot be converted to type ‘System.Int32’
To avoid this problem, convert the value to the right type. PropertyInfo.PropertyType tells you the right type, and you can use Convert.ChangeType() as a general purpose way to convert from one type to another:
string id = "5";
var idProp = movie.GetType().GetProperty("Id");
var idWithRightType = Convert.ChangeType(id, idProp.PropertyType);
idProp.SetValue(movie, idWithRightType);
Code language: C# (cs)
Note: If you know specifically what type you are converting to, you can use the specific converter instead if you want (like Convert.ToInt32()), instead of the general purpose Convert.ChangeType().
Avoid modifying a read-only property
Let’s say Movie.BoxOfficeRevenue is read-only and you’re trying to modify it:
var boxOfficeProp = movie.GetType().GetProperty("BoxOfficeRevenue");
boxOfficeProp.SetValue(movie, 86_000_000m);
Code language: C# (cs)
The behavior depends on how you defined the read-only property.
Surprisingly, you can modify the property’s value when it has a private setter (same behavior as a readonly field):
public decimal BoxOfficeRevenue { get; private set; }
Code language: C# (cs)
Note: This is technically not a read-only property, but you may want to avoid modifying its value from the outside, since declaring it with a private setter was probably done for a reason.
You can’t modify the value if the property doesn’t have a setter (a true read-only property):
public decimal BoxOfficeRevenue { get; }
Code language: C# (cs)
You’ll get the following the exception:
System.ArgumentException: Property set method not found.
To avoid this, you can check PropertyInfo.SetMethod:
var boxOfficeProp = movie.GetType().GetProperty("BoxOfficeRevenue");
if (boxOfficeProp.SetMethod != null && !boxOfficeProp.SetMethod.IsPrivate)
{
boxOfficeProp.SetValue(movie, 86_000_000m);
}
Code language: C# (cs)
It’ll be null if there’s no setter, and SetMethod.IsPrivate will be true if it was declared with a private setter.
Check for nulls
GetProperty(name) returns null if it can’t find a property with the specified name, which can lead to NullReferenceException’s.
Let’s say BoxOfficeRevenue is defined as a readonly field:
public readonly decimal BoxOfficeRevenue;
Code language: C# (cs)
And you mistakenly use GetProperty() to fetch this field:
var property = movie.GetType().GetProperty("BoxOfficeRevenue");
var val= property.GetValue(movie);
Code language: C# (cs)
Since BoxOfficeRevenue is a field, not a property, GetProperty() will return null. Since it’s trying to call .GetValue() on a null, it results in a NullReferenceException.
To avoid this problem, check if the PropertyInfo is null before using it.
var property = movie.GetType().GetProperty("BoxOfficeRevenue");
if (property != null)
{
var val = property?.GetValue(movie);
//do stuff with the value
}
Code language: C# (cs)
Filter properties by definition (name, type, etc…)
There are two main ways to filter properties:
- Pass in the BindingFlags enum flag parameter to control what GetProperties() looks for.
- Filter the returned PropertyInfo objects by looking at its properties, such as PropertyInfo.PropertyType.
By default, GetProperties() returns all public instance and static properties of a type. When you pass in the BindingFlags parameter, it overrides the default behavior. So make sure to pass in ALL of the flags you want, including re-adding the default behavior if desired (ex: BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).
I’ll show a few filtering examples below.
Get a specific property by name
If you want a specific property by name, use GetProperty() instead of GetProperties().
var property = movie.GetType().GetProperty("ReleasedOn");
Console.WriteLine(property.GetValue(movie));
Code language: C# (cs)
This outputs:
ReleasedOn=10/24/2014 12:00:00 AM
Code language: plaintext (plaintext)
By default, GetProperty() does a case sensitive search. You can do a case insensitive search like this by using BindingFlags.IgnoreCase, like this:
using System.Reflection;
var defaultFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
var propertyInfo = movie.GetType().GetProperty("releasedOn", defaultFlags | BindingFlags.IgnoreCase);
Console.WriteLine($"{propertyInfo.Name}={propertyInfo.GetValue(movie)}");
Code language: C# (cs)
This matched “releasedOn” with the ReleasedOn property and output:
ReleasedOn=10/24/2014 12:00:00 AM
Code language: plaintext (plaintext)
Get all private properties
Let’s say you want to get the following private instance properties:
private DateTime ReleasedOn { get; set; }
private decimal BoxOfficeRevenue { get; set; }
Code language: C# (cs)
To get these properties, use GetProperties() with these BindingFlags:
using System.Reflection;
foreach (var propertyInfo in movie.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance))
{
Console.WriteLine(propertyInfo.Name);
}
Code language: C# (cs)
This outputs the two private properties:
ReleasedOn
BoxOfficeRevenue
Code language: plaintext (plaintext)
Get all properties with a specific type
Let’s say you want to get all DateTime properties.
To do that, filter by PropertyInfo.PropertyType in a Where():
using System.Linq;
foreach (var propertyInfo in movie.GetType().GetProperties().Where(p => p.PropertyType == typeof(DateTime)))
{
Console.WriteLine($"{propertyInfo.Name}={propertyInfo.GetValue(movie)}");
}
Code language: C# (cs)
This outputs the following:
ReleasedOn=10/24/2014 12:00:00 AM
Code language: plaintext (plaintext)
Get all properties that have a setter
Let’s say you want to modify property values, so you only want to get properties that have a setter. For example, you want to filter out the following read-only property:
public DateTime ReleasedOn { get; }
Code language: C# (cs)
To exclude read-only properties, filter by PropertyInfo.SetMethod in a Where():
using System.Linq;
foreach (var propertyInfo in movie.GetType().GetProperties().Where(p => p.SetMethod != null))
{
Console.WriteLine($"{propertyInfo.Name}={propertyInfo.GetValue(movie)}");
}
Code language: C# (cs)
This outputs all of the properties that have a setter:
Id=10
Title=John Wick
Director=Chad Stahelski
BoxOfficeRevenue=86000000
Code language: plaintext (plaintext)
Get properties that have an attribute
You can use PropertyInfo.GetCustomAttribute<T>() to check if properties have an attribute.
For example, let’s say you have the following two properties that have the [Required] attribute:
using System.ComponentModel.DataAnnotations;
[Required]
public int Id { get; set; }
[Required]
public string Title { get; set; }
Code language: C# (cs)
Note: [Required] is one of many built-in model validation attributes.
Here’s how to filter out properties that don’t have the [Required] attribute:
foreach (var propertyInfo in movie.GetType().GetProperties()
.Where(p => p.GetCustomAttribute<RequiredAttribute>() != null))
{
Console.WriteLine($"{propertyInfo.Name} is required.");
}
Code language: C# (cs)
This outputs the following:
Id is required.
Title is required.
Code language: plaintext (plaintext)
Comments are closed.