Introduction
Clay is very similar to ExpandoObject and can be seen as an enhanced version of ExpandoObject. They allow us to construct the objects we want without needing to define a class. Compared to ExpandoObject, Clay offers more flexible syntax support, allowing us to write C# code like JavaScript, while also being able to build multi-level complex objects.

Multiple Ways to Initialize Objects
- The simplest object construction and initialization
dynamic New = new ClayFactory();
var person = New.Person();
person.FirstName = "Louis";
person.LastName = "Dejardin";
Note Here, Person is not a specific, actual class or struct. We constructed an object with FirstName and LastName properties without defining a Person class.
- Initialization using indexer
var person = New.Person();
person["FirstName"] = "Louis";
person["LastName"] = "Dejardin";
- Initialization using anonymous objects
var person = New.Person(new {
FirstName = "Louis",
LastName = "Dejardin"
});
- Initialization using named parameters
var person = New.Person(
FirstName: "Louis",
LastName: "Dejardin"
);
- Chaining initialization
var person = New.Person()
.FirstName("Louis")
.LastName("Dejardin");
Property access methods
person.FirstName
person[“FirstName”]
person.FirstName()
All three above access the FirstName property; they are equivalent.
Multiple ways of initializing objects and accessing properties make dynamic more flexible. These are things ExpandoObject cannot do.
Building Magical Arrays
We can create JavaScript-style Arrays:
dynamic New = new ClayFactory();
var people = New.Array(
New.Person().FirstName("Louis").LastName("Dejardin"),
New.Person().FirstName("Bertrand").LastName("Le Roy")
);
- The constructed Array has a Count property
Console.WriteLine("Count = {0}", people.Count);
- It can be accessed via index
Console.WriteLine("people[0].FirstName = {0}", people[0].FirstName);
- Supports foreach iteration
foreach (var person in people) {
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
- Easily adding Array properties to objects
person.Aliases("bleroy", "BoudinFatal");
Here, we are adding an Array property to the dynamic object person. The property name is Aliases, so Aliases can be replaced with any name without specific meaning.
The following code is equivalent:
persons.Aliases1(new[] {"bleroy", "BoudinFatal"});
- The element type in Array is dynamic, not a normal type
Because the element type in Array is dynamic, we can have an Array like this:
var people = New.Array(
New.Person().FirstName("Louis").LastName("Dejardin"),
"Peter"
);
Dynamically Adding Methods to Objects
Like ExpandoObject, you can also extend methods on it, but when calling the method, you need an extra (). This might be because Clay uses () to access object properties.
var person = New.Pserson();
person.FirstName = "Louis";
person.LastName = "Dejardin";
person.SayFullName = new Func<string, string>(x => person.FirstName + person.LastName + x);
Console.WriteLine(person.SayFullName()(" Here!"));
Dynamically Implementing Interfaces
Suppose we define this interface and want to create an object using dynamic types that implements this interface. Seems like an impossible task? Clay can do it!
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
dynamic New = new ClayFactory();
var people = New.Array(
New.Person().FirstName("Louis").LastName("Dejardin"),
New.Person().FirstName("Bertrand").LastName("Le Roy"));
IPerson lou = people[0];
var fullName = lou.FirstName + " " + lou.LastName;
Clay Application Background
The original intention is to solve problems once and for all by constructing a freely extensible, flexible dynamic object. That's the purpose of Clay.
Clay is an independent open-source project. With its all-powerful capabilities, it can definitely help you simplify many class definitions and reflection code.