Keywords: C# | Dynamic Types | Reflection Mechanism | PropertyInfo | GetValue Method
Abstract: This paper provides an in-depth exploration of techniques for accessing dynamic type properties via string names in C#. It thoroughly analyzes the runtime characteristics of the dynamic keyword, the working principles of reflection mechanisms, and the specific applications of the PropertyInfo.GetValue method. Through complete code examples and performance comparisons, it demonstrates how to safely and efficiently handle dynamic property access, while providing best practices for exception handling and type conversion. The article also discusses the differences between dynamic types and anonymous types, along with practical application scenarios in real-world projects.
Fundamentals of Dynamic Types and Reflection Mechanisms
The dynamic keyword in C# introduces a mechanism that bypasses type checking at compile time, deferring type resolution to runtime. This feature enables developers to handle object properties in a more flexible manner, offering significant advantages when dealing with data of unknown structure.
When declaring a dynamic variable, the compiler does not perform static type verification on member access:
dynamic dynamicObject = new { property1 = "value1", property2 = 123 };
// property1 and property2 are not checked for existence at compile time
Core Principles of Reflection Mechanism
Reflection is a powerful mechanism provided by the .NET framework that allows inspection of type information, method invocation, and property access at runtime. For dynamic type property access, reflection provides the necessary toolset.
Obtaining type information is the first step in reflection operations:
Type objectType = dynamicObject.GetType();
// Returns information about the actual type at runtime
Detailed Analysis of PropertyInfo and GetValue Method
The PropertyInfo class is a core component of the reflection API, encapsulating metadata information about properties. The GetProperty method retrieves a PropertyInfo instance for a specific property:
PropertyInfo propertyInfo = dynamicObject.GetType().GetProperty("propertyName");
if (propertyInfo != null)
{
// Property exists, proceed with further operations
}
The GetValue method is the key to actually retrieving property values, with its complete signature as follows:
public object GetValue(object obj, object[] index);
For non-indexer properties, the second parameter should be null:
object propertyValue = propertyInfo.GetValue(dynamicObject, null);
Complete Implementation Example
Combining the specific scenario from the Q&A data, the complete implementation for dynamic property access is as follows:
dynamic sampleData = new {
value1 = "sample text",
value2 = "random content",
value3 = 42
};
string propertyName = "value2";
PropertyInfo targetProperty = sampleData.GetType().GetProperty(propertyName);
if (targetProperty != null)
{
object result = targetProperty.GetValue(sampleData, null);
Console.WriteLine($"Property {propertyName} value: {result}");
}
else
{
Console.WriteLine($"Property {propertyName} does not exist");
}
Exception Handling and Robustness Design
In practical applications, various exception scenarios must be considered:
try
{
dynamic data = GetDynamicData();
string propName = "targetProperty";
PropertyInfo propInfo = data.GetType().GetProperty(propName);
if (propInfo == null)
{
throw new ArgumentException($"Property {propName} does not exist");
}
object value = propInfo.GetValue(data, null);
// Process the retrieved value
}
catch (Exception ex)
{
Console.WriteLine($"Error accessing property: {ex.Message}");
}
Performance Optimization Considerations
Reflection operations are typically slower than direct property access. In performance-sensitive scenarios, consider caching PropertyInfo instances:
private static readonly Dictionary<string, PropertyInfo> _propertyCache
= new Dictionary<string, PropertyInfo>();
public object GetCachedPropertyValue(dynamic obj, string propertyName)
{
Type objType = obj.GetType();
string cacheKey = $"{objType.FullName}.{propertyName}";
if (!_propertyCache.TryGetValue(cacheKey, out PropertyInfo propInfo))
{
propInfo = objType.GetProperty(propertyName);
if (propInfo != null)
{
_propertyCache[cacheKey] = propInfo;
}
}
return propInfo?.GetValue(obj, null);
}
Analysis of Practical Application Scenarios
The database proxy example from the reference article demonstrates the application of dynamic property access in real-world projects:
dynamic queryResult = DataAccess.GetDynamicQueryResult(
"companyName", 0, 10, "industry");
if (queryResult != null)
{
var totalRecords = queryResult.GetType()
.GetProperty("totalCount").GetValue(queryResult, null);
var pageCount = queryResult.GetType()
.GetProperty("pageCount").GetValue(queryResult, null);
var dataItems = queryResult.GetType()
.GetProperty("dataList").GetValue(queryResult, null);
// Process paged data
ProcessPagedData(totalRecords, pageCount, dataItems);
}
Balancing Type Safety and Dynamic Types
While dynamic types provide flexibility, type safety must be balanced in enterprise-level applications:
// Dynamic approach - flexible but lacks compile-time checking
dynamic flexibleData = GetExternalData();
var value = flexibleData.GetType().GetProperty("dynamicField").GetValue(flexibleData, null);
// Strongly-typed approach - safe but requires predefined structure
StrongTypeData typedData = GetTypedData();
var safeValue = typedData.PredefinedField;
Extended Application: Generic Property Accessor
Create generic property access utility classes to simplify repetitive code:
public static class DynamicPropertyAccessor
{
public static T GetPropertyValue<T>(dynamic obj, string propertyName)
{
PropertyInfo property = obj.GetType().GetProperty(propertyName);
if (property == null)
throw new ArgumentException($"Property {propertyName} does not exist");
object value = property.GetValue(obj, null);
return (T)Convert.ChangeType(value, typeof(T));
}
public static bool TryGetPropertyValue<T>(dynamic obj, string propertyName, out T result)
{
result = default(T);
try
{
result = GetPropertyValue<T>(obj, propertyName);
return true;
}
catch
{
return false;
}
}
}
Through this comprehensive analysis, readers can fully master the technical details of dynamic property access in C# and appropriately apply reflection mechanisms in actual projects, balancing flexibility with performance requirements.