C# provides pre-supplied dynamic types such as the ExpandoObject. It is also possible to create new dynamic types or add dynamic capabilities to existing custom classes.
One of the core interfaces that enables dynamic behaviour is the IDynamicMetaObjectProvider interface. Whilst this interface can be implemented, an easier way to create a custom dynamic class is to inherit from DynamicObject class.
The DynamicObject base class provides a number of virtual methods that allow an instance of the derived class to respond to dynamic operations such as getting or setting the value of a dynamically added property or invocation of a dynamic method.
The following simple example allows adding of arbitrary dynamic properties at runtime. The class overrides the TrySetMember and TryGetMember virtual methods to provide the behaviour. Notice that these methods have a binder parameter that gives information about the dynamic operation that is being attempted, such as the name of the property (binder.Name). Also note that the methods return a Boolean value to indicate to the runtime whether the dynamic operation succeeded.
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
namespace CustomDynamic
{
class MyDynamicClass : DynamicObject
{
private readonly Dictionary<string, object> _dynamicProperties = new Dictionary<string, object>();
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_dynamicProperties.Add(binder.Name, value);
// additional error checking code omitted
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return _dynamicProperties.TryGetValue(binder.Name, out result);
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var property in _dynamicProperties)
{
sb.AppendLine($"Property '{property.Key}' = '{property.Value}'");
}
return sb.ToString();
}
}
}
At runtime, if the instance of the class is declared as dynamic, arbitrary properties can be set as the following simple console application demonstrates:
using System;
namespace CustomDynamic
{
class Program
{
static void Main(string[] args)
{
dynamic d = new MyDynamicClass();
// Need to declare as dynamic, the following cause compilation errors:
// MyDynamicClass d = new MyDynamicClass();
// var d = new MyDynamicClass();
// Dynamically add properties
d.Name = "Sarah"; // TrySetMember called with binder.Name of "Name"
d.Age = 42; // TrySetMember called with binder.Name of "Age"
Console.WriteLine(d.Name); // TryGetMember called
Console.WriteLine(d.Age); // TryGetMember called
Console.ReadLine();
}
}
}
To learn more about how C# makes dynamic possible, some potential use cases, and more detail on implementing custom types check out my Dynamic C# Fundamentals Pluralsight course.
You can start watching with a Pluralsight free trial.
SHARE: