C# Reflection allows you to analyze class structures (such as properties and methods) at runtime, even if they are unknown at compile time.
The Type.GetProperties method is frequently used to retrieve a list of properties belonging to an object. To use this method effectively, it is essential to understand the BindingFlags enumeration, which allows you to filter the search results.
This article explains the meaning of the main flags and provides a practical coding example.
Key Fields of BindingFlags
By combining these flags using the bitwise OR operator (|) and passing them to GetProperties, you can control the scope of the properties retrieved (e.g., only public, including static, etc.).
| Field | Meaning |
| Instance | Includes instance members (non-static) in the search. |
| Static | Includes static members in the search. |
| Public | Includes public members in the search. |
| NonPublic | Includes non-public members (private, protected, internal) in the search. |
| DeclaredOnly | Excludes members inherited from base classes and searches only for members declared in the class itself. |
Note: You must specify at least one from the Instance/Static group AND at least one from the Public/NonPublic group. If you specify only one side, you will not retrieve the correct results.
Implementation Sample: Retrieving All Property Information
The following code defines a custom class with properties having different access modifiers and static statuses. It then uses Reflection to extract their information.
Sample Code
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
// Get type info to analyze
Type targetType = typeof(AppUser);
Console.WriteLine($"--- Properties of Class: {targetType.Name} ---");
// Set search conditions
// Instance: Instance properties
// Static: Static properties
// Public: Public properties
// NonPublic: Private/Internal properties
// DeclaredOnly: Exclude properties inherited from base classes (like object)
var flags = BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.DeclaredOnly;
// Get array of property info
PropertyInfo[] properties = targetType.GetProperties(flags);
foreach (var p in properties)
{
// Display property details
// Name: Property Name
// PropertyType: Type
// CanRead/CanWrite: Availability of get/set
Console.WriteLine($"Name: {p.Name,-15} | Type: {p.PropertyType.Name,-10} | Read: {p.CanRead} / Write: {p.CanWrite}");
}
}
}
// Sample class for analysis
public class AppUser
{
// 1. Public Instance Property
public string UserName { get; set; }
// 2. Private Instance Property
private int InternalId { get; set; }
// 3. Public Static Property
public static string DefaultRole { get; } = "Guest";
// 4. Read-Only Property
public DateTime CreatedAt { get; }
public AppUser()
{
CreatedAt = DateTime.Now;
}
}
Execution Result
--- Properties of Class: AppUser ---
Name: UserName | Type: String | Read: True / Write: True
Name: InternalId | Type: Int32 | Read: True / Write: True
Name: DefaultRole | Type: String | Read: True / Write: False
Name: CreatedAt | Type: DateTime | Read: True / Write: False
Explanation
Importance of Search Flags
If you call GetProperties() without arguments, it returns only Public + Instance + Static properties by default (it cannot retrieve private members).
If you want to control private properties or inherited properties, you must explicitly specify BindingFlags as shown in the sample code.
Using PropertyInfo
From the retrieved PropertyInfo object, you can check not only the name and type but also detailed information such as:
- CanRead, CanWrite: Checks if a getter or setter exists.
- GetCustomAttributes(): Retrieves attributes attached to the property.
