0% found this document useful (0 votes)
70 views11 pages

Tales From The Evil Empire - Clay - Malleable C# Dynamic Objects - Part 2

This document summarizes the capabilities of the Clay library for creating dynamic objects in C#. Clay allows creating dynamic objects that can be initialized and accessed in multiple equivalent ways, such as via properties, indexers, or named arguments. It also supports creating and modifying nested object graphs and arrays. Clay objects can implement interfaces to gain static type checking while maintaining dynamic behavior. The document provides examples of creating simple and complex dynamic objects using Clay's various initialization and access syntaxes.

Uploaded by

Active8
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
70 views11 pages

Tales From The Evil Empire - Clay - Malleable C# Dynamic Objects - Part 2

This document summarizes the capabilities of the Clay library for creating dynamic objects in C#. Clay allows creating dynamic objects that can be initialized and accessed in multiple equivalent ways, such as via properties, indexers, or named arguments. It also supports creating and modifying nested object graphs and arrays. Clay objects can implement interfaces to gain static type checking while maintaining dynamic behavior. The document provides examples of creating simple and complex dynamic objects using Clay's various initialization and access syntaxes.

Uploaded by

Active8
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

4/10/2015 Tales 

from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

Clay: malleable C# dynamic objects –
part 2
Wednesday, August 18, 2010
.NET (/bleroy/Tags/.NET)   ASP.NET (/bleroy/Tags/ASP.NET)   C# (/bleroy/Tags/C%23)   Clay (/bleroy/Tags/Clay)
Dynamic languages (/bleroy/Tags/Dynamic%20languages)   JSON (/bleroy/Tags/JSON)   Orchard (/bleroy/Tags/Orchard)

In the first part of this post
(http://weblogs.asp.net/bleroy/archive/2010/08/16/clay­
malleable­c­dynamic­objects­part­1­why­we­need­it.aspx),
I explained what requirements we have for the view
models in Orchard and why we think dynamic
(http://msdn.microsoft.com/en­us/library/dd264736.aspx) is
a good fit for such an object model.

This time, we’re going to look at Louis
(http://whereslou.com)’ Clay (http://clay.codeplex.com)
library and how you can use it to create object graphs and
consume them.

But before we do that, I want to address a couple of questions.

1. If we use dynamic, aren’t we losing IntelliSense and compile­time checking
and all the good things that come with statically­typed languages? And is C#
becoming overloaded with concepts, and trying to be good at everything but
becoming good at nothing?

Hush, hush, everything is going to be all right. Relax.

Now think of all the XML/DOM styles of APIs that you know in .NET (or Java for that matter). Except if
they are doing code generation, you already don’t get IntelliSense and compile­time checking. Well, you
do get them on the meta­model, which you care very little about, but not on the actual data, which you
do care a lot about. So it’s ok, we can afford to lose what we didn’t have in the first place. And there’s
always testing, right?

As for the evolution of C#, come on. You should be happy it’s still alive and innovating. Take a deep dive
into what expression trees (http://msdn.microsoft.com/en­us/library/bb397951.aspx) really mean for
example. It’s a beautiful thing.

2. What’s wrong with ExpandoObject (http://msdn.microsoft.com/en­
us/library/system.dynamic.expandoobject.aspx)?

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 1/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

Nothing but we can do better. ExpandoObject is actually implemented in a surprising way that makes it
very efficient. Hint: no dictionary in there. Other hint: it’s a beautiful thing.

But in terms of API usability it’s not very daring and in particular it does not do much to help you build
deep dynamic object graphs. Its behavior is also fixed and can’t be extended.

Clay on the other hand is highly extensible and focuses on creation and consumption of deep graphs.

Let’s get started. The first thing you can do with Clay is create a simple object and set properties on it.
Before we do that, we’ll instantiate a factory that will give us some nice syntactic semantic sugar. I wish
we could skip this step and use some kind of static API instead but we can’t. Well, small price to pay as
you’ll see:

dynamic New = new ClayFactory();

(http://11011.net/software/vspaste)
Now this “New” object will help us create new Clay objects, as the name implies (although this name is
just a convention).

Here’s something easy and not too surprising:

var person = New.Person();
person.FirstName = "Louis";
person.LastName = "Dejardin";

(http://11011.net/software/vspaste)
Nothing you couldn’t do with ExpandoObject but where this gets interesting is that there is more than one
way to skin that cat, and that is going to open up a lot of possibilities.

For instance in Clay, indexer syntax and property accessors are equivalent, just as they are in
JavaScript. This is very useful when you are writing code that accesses a property by name without
knowing that name at compile­time:

var person = New.Person();
person["FirstName"] = "Louis";
person["LastName"] = "Dejardin";

(http://11011.net/software/vspaste)
But that’s not all. You can also use properties as chainable setters, jQuery­style:

var person = New.Person()
    .FirstName("Louis")
    .LastName("Dejardin");

(http://11011.net/software/vspaste)
Or you can pass an anonymous object in if that’s your fancy:

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 2/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

var person = New.Person(new {
    FirstName = "Louis",
    LastName = "Dejardin"
});

(http://11011.net/software/vspaste)
Even better, Clay also understands named arguments, which enables us to write this:

var person = New.Person(
    FirstName: "Louis",
    LastName: "Dejardin"
);

(http://11011.net/software/vspaste)
In summary, there is a lot of ways you can set properties and initialize Clay objects.

As you’d expect, accessing properties can also be done in a number of ways and all of the following are
equivalent:

person.FirstName
person["FirstName"]
person.FirstName()

(http://11011.net/software/vspaste)
You can also create JavaScript­style arrays:

var people = New.Array(
    New.Person().FirstName("Louis").LastName("Dejardin"),
    New.Person().FirstName("Bertrand").LastName("Le Roy")
);

(http://11011.net/software/vspaste)
That array is also a full Clay object, meaning that you can add properties to it on the fly.

Then you can do this in order to count the items in the array and to access the FirstName property of the
first item in the array:

people.Count
people[0].FirstName

(http://11011.net/software/vspaste)
It’s even easier when you want to create an array property on an existing Clay object:

person.Aliases("bleroy", "BoudinFatal");

(http://11011.net/software/vspaste)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 3/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

If more than one argument gets passed in, Clay is assuming that you’re initializing the property as an
array. And if you only have zero or one arguments, just explicitly pass in an array (CLR or Clay):

person.Aliases(new[] {"Lou"});

(http://11011.net/software/vspaste)
Contrary to CLR arrays, Clay arrays can grow dynamically:

person.Aliases.Add("loudej");

(http://11011.net/software/vspaste)
And they also answer to a number of methods such as AddRange, Insert, Remove, RemoveAt, Contains,
IndexOf, or CopyTo.

Getting all this together, we can create a reasonably complex object graph with a fairly expressive and
terse syntax:

var directory = New.Array(
    New.Person(
        FirstName: "Louis",
        LastName: "Dejardin",
        Aliases: new[] { "Lou" }
    ),
    New.Person(
        FirstName: "Bertrand",
        LastName: "Le Roy"
    ).Aliases("bleroy", "boudin"),
    New.Person(
        FirstName: "Renaud",
        LastName: "Paquay"
    ).Aliases("Your Scruminess", "Chef")
).Name("Some Orchard folks");

(http://11011.net/software/vspaste)
There’s one last thing I’d like to show that I found really neat and surprising the first time Louis showed it
to me.

Imagine that you have a CLR interface that you need to implement, for example:

public interface IPerson {
    string FirstName { get; set; }
    string LastName { get; set; }
}

(http://11011.net/software/vspaste)
but you would like to do it using a Clay object such as one of the persons defined above. Well, you can
do this:

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 4/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

IPerson lou = people[0];
var fullName = lou.FirstName + " " + lou.LastName;

(http://11011.net/software/vspaste)
What’s extraordinary here is that lou is a perfectly valid statically typed CLR variable. You’ll get full
IntelliSense and compile­time checks on that code. It’s just an object that implements IPerson although
we never wrote a concrete type implementing that interface.

What makes the magic possible is that Clay is overriding the cast operator and creating a dynamic proxy
for the interface (using Castle (http://www.castleproject.org/dynamicproxy/index.html)) that delegates the
members to the Clay object.

So there is an actual CLR type but it’s being code­generated on the fly.

That is what enables you to write the following:

foreach(var person in directory) {
    Trace.Write(person.FirstName);
}

(http://11011.net/software/vspaste)
What’s happening here is that the “directory” Clay array is being cast into an IEnumerable, for which all
the right methods are implemented by the dynamic Clay array object.

We are going to dig deeper into Clay in future posts as there is so much more to do and hack but that
should give a satisfactory introduction of the basic intents for the library. I certainly hope you like it and
find some crazy ideas about how to use it.

You can find Clay here: http://clay.codeplex.com/ (http://clay.codeplex.com/)

The first part of this post is here: 
http://weblogs.asp.net/bleroy/archive/2010/08/16/clay­malleable­c­dynamic­objects­part­1­why­we­need­
it.aspx (http://weblogs.asp.net/bleroy/archive/2010/08/16/clay­malleable­c­dynamic­objects­part­1­why­
we­need­it.aspx)

23 Comments

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 5/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

The implicit casting (coin term: molding?) is brilliant and would seem useful for other scenarios too.
For example, you've got an IDictionary and you want to treat it as an interface that defines some
properties that happen to be keys in the dictionary. 

ISomething something = Clay.Proxy(dictionary); 
something.Value1 = 1; // dictionary["Value1"] = 1; 

For gets, it could also implicitly 'mold' the value, for cases where the value itself is also a dictionary:

Foo foo = something.PropertyOfTypeFoo; 
// Clay.Proxy(typeof(Foo), dictionary["PropertyOfTypeFoo"]) 

This would be great for JSON deserialization from JavaScriptSerializer, where you've got a
hierarchy of objects as dictionaries that all boil down to just simple values in the leaves. Currently
you pretty much have to manually build the objects from the Dictionary. 
—  InfinitiesLoop (http://weblogs.asp.net/InfinitiesLoop/) ­ Wednesday, August 18, 2010 5:58:07 PM (/bleroy/clay­
malleable­c­dynamic­objects­part­2#comment­986)

Awesome! 

It would be cool if Clay would also allow access events that could be set like in jQuery. 

so Person.FirstName() would return the first name and Person.FirstName(x => LogAccess(x)); 
or whatever other function you may want to hook in. This could allow the setter of the data to hook
in and see who accessed it. Could be very useful in a CMS type environment where you may have
multiple modules adding data and multiple partial views accessing it. 

Besides all ofthis. How is performance? 
—  srulyt ­ Wednesday, August 18, 2010 6:12:19 PM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­987)

This is cool! 

My question is if Clay object supports data binding? 
—  yysun ­ Wednesday, August 18, 2010 7:26:11 PM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­988)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 6/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

@InfinitiesLoop: yep, that would be an interesting application. Actually, serialization/deserialization
is something that would be interesting to add. 

@srulyt: well, the good news is that this would be fairly easy to add as an extension. More on that
in future posts. The bad news is that assigning a Lambda to a dynamic member is not as easy as it
sounds: the C# compiler doesn't let you do it without some expression goo. 
As for performance, we haven't looked at it yet, and it's using dictionaries internally but in principle
it could use the same tricks that ExpandoObject is using and get quite fast. Anyway, for the
moment we want to use that where performance is not a big issue and where convenience is way
more important. 

@yysun: not yet. What exactly do you have in mind? 
—  Bertrand Le Roy (http://weblogs.asp.net/bleroy/) ­ Wednesday, August 18, 2010 8:11:57 PM (/bleroy/clay­malleable­c­
dynamic­objects­part­2#comment­989)

wait, I do get intellisense/serialization/compile time errors etc when I make classes for data...? Why
is that the wrong way again? 
—  Robin Debreuil (http://blog.debreuil.com) ­ Wednesday, August 18, 2010 9:40:25 PM (/bleroy/clay­malleable­c­dynamic­
objects­part­2#comment­990)

@Robin: it's not "the wrong way" if it works for what you're doing. But you need to create a new
class for each shape and more importantly you can't graft new members after the fact. With this,
you can have a multitude of agents contributing to building the same object graph and adding stuff
that wasn't planned for initially. 
—  Bertrand Le Roy (http://weblogs.asp.net/bleroy/) ­ Wednesday, August 18, 2010 9:46:19 PM (/bleroy/clay­malleable­c­
dynamic­objects­part­2#comment­991)

This is amazing. Just tested it out and it feels very smooth. 

The only thing is that you lose Intellisense when you pass the created object graph into a View of
an MVC app (ViewPage). 

Still doing perfectly renders the correct value of course. 

Or is there a way to "enforce" Intellisense for a dynamic type? 
—  Vincent (http://postback.be/blog) ­ Thursday, August 19, 2010 5:33:16 AM (/bleroy/clay­malleable­c­dynamic­objects­part­
2#comment­992)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 7/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

I'm pretty sure you would agree 'less typing' isn't a good reason to give up compile time safety, but
I've done a ton of AS/JS and understand the attraction 

I've never really worked in a domain where I needed to munge unknown types together at runtime
though. REALLY not questioning it, I know everyone has a different set of problems in different
domains ­ I am curious what kind of things that is though..? Is that like user generated data? This
is OT, feel free to ignore, but isn't handling data like that basically impossible anyway? Or is it more
wrap it and send along, or just display it? Or maybe you get code that handles the objects from the
same source? 

Always cool to look at problems through the eyes of others : ). 

To be honest, I do cringe a little seeing C# able to run blind like JS, but if you are authoring it I'm
sure it is sensible and in good hands : ). 
—  Robin Debreuil (http://blog.debreuil.com) ­ Thursday, August 19, 2010 7:01:26 AM (/bleroy/clay­malleable­c­dynamic­
objects­part­2#comment­993)

@Vincent: as the article shows, you can cast into an interface type and get IntelliSense but if are
willing to do that, it's actually quite likely that you will get little benefit from not using a statically­
typed object as your model. 

@Robin: community­created modules can all chime in on the creation and enrichment of any node
in the tree of view data that can be displayed on an Orchard page by community­created themes.
Even a specific node might get enriched with new properties and children by multiple agents.
You've got tiny bits of data being collaboratively composed into the view model, and tiny bits of
themed templates rendering them. 
What you trivialize by referring to it by "less typing" is actually quite important. In particular when
dealing with a designer audience, being able to write item.title rather than
item.Attributes["title"].Value is very important. And as I said in the article, you *already don't* get
IntelliSense on what matters here, the data. 
It shouldn't be that surprising that people prefer to manipulate an HTML DOM using jQuery rather
than the native DOM API. One is fluent, dynamic and concretely data­centric while the other is
static and focuses on the abstract structure of the tree. 
Same thing here. I'm certainly not advocating that you use Clay where you can easily create a
good static model. But there are are many cases where a dynamic type works a lot better. 
—  Bertrand Le Roy (http://weblogs.asp.net/bleroy/) ­ Thursday, August 19, 2010 7:46:01 AM (/bleroy/clay­malleable­c­
dynamic­objects­part­2#comment­994)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 8/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

I really believe that dynamic does have it's place in C#. In many cases it's better to rely on static
typing, but sometimes static typing just get's in your way (reflection, DOM­style API, XML, ...). 

I like how you can 'opt in' to dynamic in C#, simply by using the 'dynamic' keyword. It gives us best
of both worlds. At the same time, the built­in dynamic features are pretty lame, so Clay fills in a gap
here. This stuff *should* have been in the framework in the first place. It is what
`dynamic`/ExpandoObject/whatever should have been. 

Very nice work. 
—  jeroenh ­ Thursday, August 19, 2010 8:42:38 AM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­995)

I'm currently using ExpandoObject with JSON.net too serialize/de­serialize between json and
dynamic objects, it makes handling interaction between a javascript client much easy. 
But you library looks an even better match than ExpandoObject for handling JSON on the server. 
—  Tony Steele ­ Thursday, August 19, 2010 9:45:56 AM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­996)

Hear, hear. Great post. 
—  Matt ­ Thursday, August 19, 2010 1:08:02 PM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­997)

cool, thanks for the description ­ checking out Orchard now... 

I'm certainly not advocating using attr["foo"] vs attr.foo, just I never really need either in the domain
I work in. I'm sure it makes sense in domains like Orchard. 

And you aren't saying people should use dynamic where they know things at compile time, so
seems like we agree all around : ). 

btw, cool name, it evoke 'written in stone' vs 'written in clay' with just four letters : ) 
—  Robin Debreuil (http://blog.debreuil.com) ­ Friday, August 20, 2010 12:08:28 AM (/bleroy/clay­malleable­c­dynamic­
objects­part­2#comment­998)

Way cool! Thanks for sharing this. I'll try Clay over the weekend ­ it looks like the domain
requirements of the app I'm working on are quite similar to Orchard's... 
—  ms440 ­ Friday, August 20, 2010 5:53:25 AM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­999)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 9/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

Is there any way I can find what props were already set on the Clay object? 

In DynamicObject I could cast it to IDictionary and get the Keys. Is something similar is possible in
Clay? 

Thanks! 
—  ms440 ­ Friday, August 20, 2010 11:57:18 PM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­1000)

@ms440: yes, reflection capabilities need to be added. This being said, I think you should be able
to cast a Clay object into IDictionary already. 
—  Bertrand Le Roy (http://weblogs.asp.net/bleroy/) ­ Saturday, August 21, 2010 12:01:53 AM (/bleroy/clay­malleable­c­
dynamic­objects­part­2#comment­1001)

My head just exploded... is this C#? 
—  Mike ­ Friday, October 29, 2010 7:55:51 PM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­1002)

Has anyone done some benchmark of Clay against Dictionary and casting? Dynamic type is from
my experience 3x slower than casting an object (if not more). 
—  Jace ­ Friday, April 15, 2011 8:06:06 AM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­1003)

@Mike: yes. 

@Jace: not that I know of. Still, *what* dynamic types are you talking about? There are many ways
that you can implement a dynamic object. Clay is not especially optimized for performance and
uses dictionaries inside. Other implementations use expression trees, a method that is much faster
than dictionaries and almost as fast a statically typed code. 
In the end, using dynamic objects means sacrificing some performance for extreme flexibility.
Ruby, Python and JavaScript developers usually consider it's a tradeoff they're willing to make. If to
you performance is the most important maybe you should switch to assembly language. Kidding. 
—  Bertrand Le Roy (http://weblogs.asp.net/bleroy/) ­ Friday, April 15, 2011 6:26:25 PM (/bleroy/clay­malleable­c­dynamic­
objects­part­2#comment­1004)

Very nice and very relevant. This is exactly the kind of thing C# needs for things that just can't be
statically typed. I absolutely love the fact that you can assign a ... Clay object? ... to an interface.
Then just carry on statically. 
—  Richard Hein ­ Saturday, May 7, 2011 3:17:02 AM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­1005)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 10/11
4/10/2015 Tales from the Evil Empire ­ Clay: malleable C# dynamic objects – part 2

A big circle, isn't it? .NET slowly becomes a dynamic scripting language ... ;) This aside, what
about dynamic get/set methods for a property and what about some access to the instance, I
should probably read on the codeplex first, but I felt like posting a comment ;) 
—  Michael ­ Sunday, January 22, 2012 6:42:10 PM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­1006)

How do I find all the dynamic properties at runtime? to access them, it's fine with your example you
know firstname & lastname, but what happens when even the property names are set at
runtime? 

TIA 

Fred 

—  Fred ­ Monday, September 10, 2012 12:26:13 AM (/bleroy/clay­malleable­c­dynamic­objects­part­2#comment­1007)

@Fred: it's up to each behavior to implement this or not. The Array behavior for example can be
cast to IEnumerable. 
—  Bertrand Le Roy (http://weblogs.asp.net/bleroy/) ­ Monday, September 10, 2012 4:40:08 PM (/bleroy/clay­malleable­c­
dynamic­objects­part­2#comment­1008)

Comments have been disabled for this content.

Terms Of Use (http://www.asp.net/terms­of­use) ­ Powered by Orchard (http://www.orchardproject.net)

https://weblogs.asp.net/bleroy/clay­malleable­c­dynamic­objects­part­2 11/11

You might also like