Dynamic Property Addition to ExpandoObject in C#: Implementation and Principles

Dec 06, 2025 · Programming · 14 views · 7.8

Keywords: ExpandoObject | Dynamic Properties | C# Programming

Abstract: This paper comprehensively examines two core methods for dynamically adding properties to ExpandoObject in C#: direct assignment through dynamic typing and using the Add method of the IDictionary<string, Object> interface. The article provides an in-depth analysis of ExpandoObject's internal implementation mechanisms, including its architecture based on the Dynamic Language Runtime (DLR), dictionary-based property storage structure, and the balance between type safety and runtime flexibility. By comparing the application scenarios and performance characteristics of both approaches, this work offers comprehensive technical guidance for developers handling dynamic data structures in practical projects.

The Dynamic Property Extension Mechanism of ExpandoObject

Within the dynamic programming model introduced in C# 4.0, the ExpandoObject class provides a flexible approach to dynamically add and manipulate properties at runtime. This capability enables developers to handle data with structures that cannot be determined at compile time, particularly useful for scenarios such as interoperability with dynamic languages, processing JSON data, or building extensible configuration systems.

Analysis of Core Implementation Methods

According to best practices, there are two primary standard methods for dynamically adding properties to ExpandoObject, each with specific use cases and implementation principles.

Method One: Direct Assignment via Dynamic Typing

The first method utilizes C#'s dynamic keyword to achieve dynamic extension through simple property assignment syntax:

dynamic x = new ExpandoObject();
x.NewProp = string.Empty;

The advantage of this approach lies in its concise and intuitive syntax, which is completely consistent with property assignment operations on statically typed objects. In terms of underlying implementation, when code invokes property setters through the dynamic type, the Dynamic Language Runtime (DLR) intercepts the call and adds corresponding key-value pairs to ExpandoObject's internal dictionary. This mechanism ensures a balance between type safety and runtime flexibility while maintaining good code readability.

Method Two: IDictionary Interface Operations

The second method involves casting ExpandoObject to the IDictionary<string, Object> interface and using standard dictionary manipulation methods:

var x = new ExpandoObject() as IDictionary<string, Object>;
x.Add("NewProp", string.Empty);

This approach is more suitable for scenarios requiring batch property operations or conditional property addition. Since ExpandoObject internally maintains a Dictionary<string, object> to store dynamic properties, accessing through the interface allows direct manipulation of this underlying data structure. This method provides greater control capabilities, particularly more appropriate when checking property existence or implementing complex logical judgments.

In-Depth Analysis of Implementation Principles

The dynamic property capability of ExpandoObject is built upon the .NET framework's Dynamic Language Runtime (DLR). The DLR provides infrastructure for dynamic language interoperability, while ExpandoObject represents a concrete manifestation of this infrastructure within C#.

From an implementation perspective, ExpandoObject implements several key interfaces:

When accessing ExpandoObject through the dynamic keyword, the DLR creates a DynamicMetaObject to handle member binding. This meta-object generates corresponding expression trees based on operation types (get, set, invoke, etc.), which are ultimately compiled into efficient delegate code.

The specific implementation of property storage employs a thread-safe dictionary structure. When adding a new property, ExpandoObject executes the following steps:

  1. Validates whether the property name conforms to C# identifier naming conventions
  2. Adds key-value pairs to the internal dictionary
  3. Triggers PropertyChanged events (if listeners are registered)
  4. Updates dynamic binding cache to improve subsequent access performance

Performance Considerations and Best Practices

While ExpandoObject offers significant flexibility, developers should be aware of its performance characteristics:

In practical applications, it is recommended to follow these best practices:

  1. For dynamic data with known structures, consider using anonymous types or custom classes
  2. Use ExpandoObject in scenarios requiring truly dynamic extension
  3. Perform batch operations through the IDictionary interface to improve performance
  4. Utilize property change notification mechanisms appropriately

Application Scenarios and Extended Considerations

The dynamic property capability of ExpandoObject plays an important role in multiple practical scenarios:

It is worth noting that while ExpandoObject provides dynamic property support, it does not support dynamic method addition. If dynamic methods are required, consider using the DynamicObject class and overriding methods such as TryInvokeMember.

With the evolution of the C# language, new patterns like pattern matching and record types also provide additional options for handling dynamic data. Developers should choose the most appropriate technical solution based on specific requirements, finding the optimal balance between flexibility and type safety.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.