Many .NET developers have heard of the Dynamic Language Runtime (DLR) but they don’t quite know what to make of it. Developers working in languages like C# and Visual Basic sometimes shirk dynamic programming languages because they fear the scalability problems that have historically been associated with using them. Also of concern is the fact that languages like Python and Ruby don’t perform compile-time type checking, which can lead to runtime errors that are very costly to find and fix. These are valid concerns that may explain why the DLR hasn’t enjoyed more popularity among mainstream .NET developers in the two years since its official release. After all, any .NET Runtime that has the words Dynamic and Language in its title must be strictly for creating and supporting languages like Python, right?

Not so fast. While it’s true that the DLR was conceived to support the “Iron” implementations of the Python and Ruby programming languages on the .NET Framework, the architecture of the DLR provides abstractions that go much deeper than that. Under the covers, the DLR offers a rich set of interfaces for performing runtime Inter-Process Communication (IPC). Over the years, developers have seen many tools from Microsoft for communicating between applications: DDE, DCOM, ActiveX, .NET Remoting, WCF, OData. The list just goes on and on. It’s a seemingly unending parade of acronyms, each one representing a technology that has promised to make it easier to share data or to invoke remote code this year than it was using last year’s technology. In this article, I’ll show you why you may want to consider using the DLR as a communication tool, even if you never intend to use a dynamic programming language in your own application designs.

The “Language of Languages”

The first time I heard Jim Hugunin speak about the DLR, his talk surprised me. Jim created an implementation of the Python language to run on the Java Virtual Machine (JVM) known as Jython. At the time of the talk, he had recently joined Microsoft to create IronPython for .NET. Based on his background, I expected him to focus on the language but Jim spent nearly the entire time talking about heady stuff like expression trees, dynamic call dispatch and call caching mechanisms, instead. What Jim described was a set of runtime compiler services that would make it possible for any two languages to communicate with one another in a high performance way.

During that talk, I jotted down the term that popped into my mind as I heard Jim retell the architecture of the DLR: the language of languages. Four years later, that moniker still characterizes the DLR pretty well. With some real-world DLR experience under my belt, however, I’ve come to realize that the DLR isn’t just for language interoperability. With dynamic type support now baked into C# and Visual Basic, the DLR has become a gateway from our favorite .NET languages to the data and code in any remote system, no matter what kind of hardware or software it may use.

Figure 1: The initiator invokes the foo function on the target.

To understand the idea of the DLR as a language-integrated, IPC mechanism, let’s begin with an example that has nothing to do with dynamic programming languages at all. Imagine two computing systems: one called the initiator and the other called the target. The initiator needs to invoke a function named foo on the target passing some number of parameters and retrieving the results.

After locating the target system, the initiator must bundle all of the necessary call information together in a format that can be understood by the target. At a minimum, this includes the name of the function and the parameters to be passed. The initiator then sends the request to the target. After unpacking the request and validating the parameters, the target may execute the foo function. Then the target system must package up the results, including any exceptions that may have occurred, and send them back to the initiator. Lastly, the initiator must unpack the results and respond appropriately. This request-response pattern is common, describing at a high level how almost every call-based IPC mechanism works.

The DynamicMetaObject Class

To understand how the architecture of the DLR fits this pattern, let’s explore one of the DLR’s central classes called the DynamicMetaObject. We’ll begin by examining three of the twelve core methods in that type:

  1. BindCreateInstance - create or activate an object
  2. BindInvokeMember - call an encapsulated method
  3. BindInvoke - execute the object (as a function)

When you need to call a method in a remote system, the first thing to do is create an instance of the type. Of course, not all systems are object-oriented so the term instance may be metaphorical. In fact, the target service may be implemented as an object pool or as a singleton so the terms activation or connection might apply as well as instantiation.

Other runtime frameworks follow this same pattern. The Component Object Model (COM) provides the CoCreateInstance function for creating objects. With .NET Remoting, you might use the CreateInstance method of the System.Activator class. The DLR’s DynamicMetaObject provides BindCreateInstance for a similar purpose.

After using the DLR’s BindCreateInstance, the created thing you have in hand may be of a type that supports multiple methods. The metaobject’sBindInvokeMember method is used to bind an operation that can invoke the function. In the graphical example from above, the string “foo” would be passed as a parameter to let the binder know that the member method by that name should be called. Also included with the parameter are useful bits of information like the argument count, argument names and a flag that says whether or not the binder should ignore case when trying to find the named member. After all, some languages are picky about the case of their symbols and some are not.

When the thing returned from BindCreateInstance is just a single function (or delegate) however, the metaobject’s BindInvoke method is used instead. To make this clear, consider the following small bit of dynamic C# code:

delegate void IntWriter(int n);
    
void Main() {
  dynamic Write =
    new IntWriter(Console.WriteLine);
  Write(5);
}

This code isn’t the optimal way to write the number 5 to the console. A good developer would never do something so wasteful. However, this code illustrates the use of a dynamic variable that is a delegate, which can be called like a function. If the delegate type were derived to implement a DLR interface named IDynamicMetaObjectProvider, the BindInvoke method of the DynamicMetaObject that it returns would be called to attach an operation to do the work. This is because the C# compiler recognizes that the dynamic object called Write is being used syntactically like a function. Now look at another bit of dynamic C# code to understand when BindInvokeMember might be emitted by the compiler instead:

class Writer :
  IDynamicMetaObjectProvider {
  public void Write(int n) {
    Console.WriteLine(n);
  }
  // interface implementation omitted
}
    
void Main() {
  dynamic Writer = new Writer();
  Writer.Write(7);
}

I’ve omitted the implementation of the interface in this small example because it would take lots of code to show you how to do that correctly. In a following section, however, we’ll take a shortcut and implement a dynamic metaobject with just a few lines of code.

The important thing for you to understand at this point is that the C# compiler recognizes the statement Writer.Write(7) as a member access operation. What we often call the “dot operator” in C# is formally called the member access operator. The DLR code generated by the compiler in this case would ultimately call BindInvokeMember, passing the string “Write” and the integer argument 7 to an operation that can perform the invocation. In short, BindInvoke is used to call a dynamic object that is a function while BindInvokeMember is used to call a method that is a member of a dynamic object.

Access to Properties via DynamicMetaObject

It’s clear to see in these two small examples that the C# compiler is using its language syntax to deduce which DLR binding operations should be performed. If you were using Visual Basic to access dynamic objects, the semantics of that language would be used instead. The member access (dot) operator doesn’t just access methods, of course. You can access properties in C# using that same operator. The DLR metaobject provides three more useful methods to access properties on dynamic objects:

  1. BindGetMember - get a property value
  2. BindSetMember - set a property value
  3. BindDeleteMember - delete a member

The purpose of BindGetMember and BindSetMember might be obvious, especially since you know that they pertain to the way that .NET uses the properties of a class. When the compiler evaluates get (or read) operations on a property of a dynamic object, it emits a call to BindGetMember. When the compiler evaluates set (or write) operations on a property, it makes sure that BindSetMember is emitted instead.

Treating an Object as an Array

Some classes behave as containers for instances of other types. So, the DLR metaobject has methods to handle these cases. Each of the array-oriented metaobject methods ends with the term "Index":

  1. BindGetIndex -get the value at a specific index
  2. BindSetIndex - set the value at a specific index
  3. BindDeleteIndex - delete the value at a specific index

To understand how BindGetIndex and BindSetIndex are used, imagine a DLR-enabled wrapper class called JavaBridge that can load Java class files and expose them to .NET code without a lot of ceremony. Such a class might be used to load a Java class file called Customer.class that contains some Object-Relational Mapping (ORM) code. A DLR metaobject can be created to invoke that ORM code from .NET in a very natural way. Here’s an example in C# that shows how the JavaBridge might work in practice:

1: JavaBridge java = new JavaBridge();
2: dynamic customers =
     java.Load("Customer.class");
3: dynamic Jason = customers["Bock"];
4: Jason.Balance = 17.34;
5: customers["Wagner"] =
     new Customer("Bill");

Lines 3 and 5 in the listing above will be interpreted by the C# compiler as index accesses because of the use of the index access ([]) operator that was used. Behind the scenes, the custom DLR metaobject for the types exposed by the JavaBridge will then receive calls to their BindGetIndex and BindSetIndex methods, respectively, to pass calls to a waiting JVM via Java Remote Method Invocation (RMI). In this scenario, the DLR helps us to bridge the gap between C# and a statically-typed language, perhaps making it clearer why I call the DLR the language of languages.

Just like the BindDeleteMember method, the BindDeleteIndex method is not intended for use from statically typed languages like C# and Visual Basic. Those languages have no way to express such a concept. However, you can establish a convention for deleting members from a class at runtime to get that kind of functionality if it’s valuable to you. For example, setting an index to null, which can be expressed in C# and Visual Basic, could be interpreted by your metaobject to mean the same thing as BindDeleteMember.

Conversion and Operations

The last group of DLR metaobject methods concerns the handling of operations and type conversions. These are:

  1. BindConvert - convert an object to another type
  2. BindBinaryOperation - invoke a binary operator on two supplied operands
  3. BindUnaryOperation - invoke a unary operator on one supplied operand

The BindConvert method gets used whenever the compiler determines that it needs to convert a dynamic object to some known type. This happens implicitly when assigning the result of a dynamic invocation to a non-dynamic data type. For example, in the following small C# example, the assignment to the variable y forces a call to BindConvert in the emitted code.

dynamic x = 13;
int y = x + 11;

The BindBinaryOperation and BindUnaryOperation methods are used whenever an operator such as arithmetic addition (+) or increment (++) is encountered. In the example above, the addition of the dynamic variable x to the constant 11 will emit a call to BindBinaryOperation method. Keep this tiny example in your mind’s eye for a moment. We use it in the next section to grok another key DLR class known as the call site.

Dynamic Dispatch via Call Sites

If the extent to which you use and understand the DLR never progressed beyond the dynamic keyword, you would probably never know what a call site was or that it even existed as a type in the .NET Framework. This humble type, formally known as CallSite<T>, exists in the System.Runtime.CompilerServices namespace. It’s a powerhouse of metaprogramming goodness; jam packed with all sorts of performance-optimizing techniques that make your dynamic .NET code fast and efficient. I’ll cover the performance aspects of the CallSite<T> class at the end of this article.

Much of what call sites do in dynamic .NET code concerns runtime code generation and compilation. So, it’s significant to note that the CallSite<T> class is implemented in a namespace that contains both of the words Runtime and CompilerServices. If the DLR is the language of languages, then the CallSite<T> class is one of its major grammatical constructs. Let’s take a look at the tiny example from the last section one more time to get familiar with call sites and how compilers like C# inject them into our code:

dynamic x = 13;
int y = x + 11;

From what you’ve learned so far, you know that calls to BindBinaryOperation and BindConvert will be emitted by the C# compiler for this bit of code. Rather than showing you the long Microsoft Intermediate Language (MSIL) disassembly of what the compiler produces, I’ve included Figure 2, a flowchart that describes the compiler’s output instead.

Figure 2: Flow of BinaryOperation and Convert.

Remember that the C# compiler uses its own syntax to determine what actions are required on the dynamic type. In the current example, there are two operations to emit: the addition of variable x to an integer (Site2) and the conversion of the result into an integer (Site1). Each of these actions becomes a call site which is stored in a container for the enclosing method. As you can see in the flowchart in Figure 2, the call sites are created in reverse order in the beginning but invoked in the correct order at the end.

You can see in the flowchart that the BindConvert and BindBinaryOperation metaobject methods are called just before the “Create Call Site 1” and “Create Call Site2” steps, respectively. Yet, the invocation of the bound operations doesn’t occur until the very end. Hopefully, the graphic helps you to understand that binding is not the same thing as invoking in the DLR. Moreover, binding happens once per the creation of each call site. The invocations, on the other hand, may occur many times over, reusing the initialized call sites to optimize performance.

Before I dive into more of the performance optimizations that the DLR uses to make dynamic code efficient and fast, let’s take a look at a simple way to implement the IDynamicMetaObjectProvider contract I mentioned earlier in one of your own classes.

A Simple Example, the Easy Way

At the heart of the DLR, Expression Trees are used to generate the functions attached by the twelve binding methods introduced earlier. While many developers have used Expression Trees indirectly via lambda expressions in Language Integrated Query (LINQ), few have the deep experience necessary to implement the complete IDynamicMetaObjectProvider contract very well. Fortunately, the .NET Framework includes a base class called DynamicObject that does a lot of the work for you.

In this section, I’ll show you how to build a dynamic, Open Data (OData) Protocol class based on the DLR’s DynamicObject type, which contains the following twelve virtual methods:

  1. TryCreateInstance
  2. TryInvokeMember
  3. TryInvoke
  4. TryGetMember
  5. TrySetMember
  6. TryDeleteMember
  7. TryGetIndex
  8. TrySetIndex
  9. TryDeleteIndex
  10. TryConvert
  11. TryBinaryOperation
  12. TryUnaryOperation

Do the names of those twelve virtual methods look familiar? They should since you just finished studying the members of the abstract DynamicMetaObject class which includes methods like BindCreateInstance and BindInvoke. The DynamicMetaObject class implements the IDynamicMetaObjectProvider, which returns a DynamicMetaObject from its single method. The operations bound to the underlying metaobject implementation simply dispatch their calls to the methods beginning with “Try” in the DynamicObject instance. All you have to do is override the methods like TryGetMember and TrySetMember in a class that derives from DynamicObject and a metaobject working behind the scenes handles all the messy Expression Tree details.

A Dynamic OData Class

To see how this works in practice, I’ll show you the design for a dynamic class that can fetch an arbitrary OData feed and parse it while providing a very native-looking syntax in C# or Visual Basic. The goal is to be able to connect to an OData as shown in Listing 1.

After getting the title of a movie and formatting the query URL to get data from the Netflix OData service, a DynamicOData class is instantiated. The OnDataReady event is subscribed and the object is instructed to fetch the OData asynchronously. When the data is ready, the OnNetflixMovieReady method shown in Listing 2 will be called. It uses a helper method called Dump that simply writes formatted strings to the console window.

After running the code in Listing 2 from the sample application, querying for data about the movie When Harry Met Sally, you’ll see output on the console window that looks something like Figure 3.

Figure 3: Dynamically accessing Netflix data.

The first thing to notice about the OnNetflixMovieReady method shown in Listing 2 is that the movie parameter is marked as dynamic. This will force the C# compiler to create a site container for the method and store call sites within it. To make this clear, the first line of dynamic access code actually produces three call sites within the container:

movie.BoxArt.SmallUrl.Value

Do you see how the member access (dot) operator is used three times in C# expression? Each of them will produce a call site within the site container for the OnNetflixMovieReady method. Of course, all of that happens behind the scenes. The C# compiler takes care of all that hard work for you.

Managing Data Inside Your Dynamic Class

The question is: how is it possible that properties like BoxArt and SmallUrl, which are very specific to the Netflix data, are made available to the C# code without any ceremony? The answer to that question is in the implementation of the TryGetMember virtual method which we’ll explore in a bit. To understand how TryGetMember works, however, you first need to understand how the DynamicOData class manages its data internally. The portion of the DynamicOData class that initializes the data from the OData feed is shown in Listing 3.

The DynamicOData class begins by setting up a delegate and an event to handle the OnDataReady event. Then a couple of namespaces are declared: one for data services common to the OData Entity Data Model (EDM) and another for the metadata. When parsing the output of an OData feed, these are necessary for addressing the Atom-encoded XML elements correctly. An IEnumerable<XElement> called _current serves as the storage for the DynamicOData node.

The FetchAsync command starts the download of the XML document using a WebClient instance. When the transfer of the XML document is complete, the OnDownloadCompleted method is invoked where the XML text is parsed into an XDocument from which the <properties> elements are collected and stored in the _current enumeration. All of the OData we’ll be using from any feed can be found in the <properties> collection. Listing 4 shows a subset of the <properties> collection as XML for one movie in the Netflix OData feed.

Lastly, after the XML document has been parsed and queried, the OnDataReady event is fired to let the caller know that the object is ready for use.

Implementing Member Access

Now that you know that the XML from the OData feed is managed as an enumeration of XElement objects, you’re ready to understand how TryGetMember is implemented. Listing 5 shows an abbreviated version of the TryGetMember method to get started.

The TryGetMember method shown in Listing 5 takes two parameters: one for the binder and an output parameter called result. If we’re successful in locating the member named in the binder.Name property, I’ll simply store the value into the result parameter which the DLR will hand back to the calling context.

A special pseudo-property called Value is made available at the beginning of the TryGetMember method. I included this pseudo-property because I know that I will want to parse the OData feed with bits of chained property expressions that looks like this:

movie.BoxArt.SmallUrl.Value

Because OData can be deeply nested like the sample shown in Listing 4, I want to be able to chain property accessed together fluently until I reach the node that has the value I’m interested in. In the case of the single C# statement above, I know that I want the Value of the SmallUrl property within the BoxArt property of the movie. The code to do that when the Value pseudo-property is encountered returns the _current enumeration’s first XElement’s Value property as a string, for now. I omitted some code at that point to keep things simple but we’ll get back to it in a bit.

If TryGetMember doesn’t encounter the use of the Value pseudo-properties, it processes the request first as if it were trying to obtain the value of an XML attribute then as a named XML element. This is also special handling because of the nature of XML text. Some data that I want to access may be encoded as an XML attribute. Other data may be encoded as an XML element. For this implementation, I’ve decided that I don’t want to have to use any kind of special syntax or another pseudo-property to get at attribute data. I’ve chosen by convention to return matching attributes if they exist, then matching elements. Of course, this won’t work in every case but it does highlight the fact that when you’re designing your own dynamic objects, you’re in the driver’s seat. In other words, working within the syntax of the host language, you’re free to implement any kind of convention that makes sense for the semantics that you’re trying to create.

Finishing up Listing 5, when the specified binder.Name property doesn’t reference a pseudo-property or an attribute, the queried Descendents of the _current XML elements are returned. It’s important to note that the enumeration of XElement objects obtained this way isn’t returned directly to the caller. I could do that, of course, but I want to be able to chain this result to another one. More importantly, I want my Value pseudo-property and XML attribute handling semantics to apply to the node that’s returned. The easiest way to do that is to return the resulting XML nodes wrapped in a new DynamicOData object. A special constructor is provided to handle this case:

protected DynamicOData(
  IEnumerable<XElement> current)
{
  _current = new List<XElement>(current);
}

While the original DynamicOData object was created for fetching XML over the network, this special constructor creates a new one at the selected level of the XML hierarchy. The C# expression movie.BoxArt will return a new DynamicOData object having its _current variable scoped to the <d:BoxArt> node of the XML. Then using the member access (dot) operator on that object, followed by SmallUrl will return another new DynamicOData object scoped to the <d:SmallUrl> node. Finally, accessing the Value pseudo-property on that last dynamic object stops the chain. To finish up our examination of TryGetMember, I need to address the code that I omitted from Listing 5. To do that, think about this line of code you saw earlier.

Dump("Runtime = {0} minutes",
  movie.Runtime.Value / 60);

How is it possible for the Value pseudo-property of the Runtime element, which is returned by TryGetMember as a string, to be divisible by the number 60 in C#? The answer is that it’s not, of course. C# isn’t that kind of dynamic language, at least not yet. To make this kind of code possible in a statically-typed language, we can take advantage of some hints in the OData data. OData’s Entity Data Model (EDM) defines a handful of abstract types for things like integers, dates, Boolean values, etc. Some OData elements are marked with an attribute named type to tell you how the text (or nested XML) contained within an element should be interpreted. Listing 6 shows the code removed from Listing 5 that provides this functionality whenever the Value pseudo-property is accessed.

Of course, to keep things short and sweet, I didn’t include conversions for all sixteen of OData’s abstract types. The full source code for this example does include them, though. The code in Listing 6 looks at a Value node for an attribute named type. If it’s found, the value of the attribute is checked against one of the sixteen known EDM data type names. If it matches, a conversion is performed to coerce the value into the expected data type. In this way, expressions like movie.Runtime.Value / 60 work correctly at runtime.

With respect to member access, I’ve spent a lot of time talking about TryGetMember but no time talking about how to modify data dynamically. The Netflix OData feed that I’ve been working with so far is read-only but other OData feeds are read-write. I won’t show the code here but it would be easy enough to add a Save method to the DynamicOData class to handle the update process if you needed that sort of functionality. The question is: how can I make modifications in a DynamicOData instance using the same fluent syntax that I’ve been using to read data? An overridden TrySetMember like this should do it:

public override bool TrySetMember(
  SetMemberBinder binder, object value)
{
  if (binder.Name == "Value")
  {
    _current.ElementAt(0).Value =
      value.ToString();
    return true;
  }
  return false;
}

With this new method in place, C# code like this becomes possible:

movie.BluRay.Available.Value = true;

Because the object returned for the Available node in that C# statement is a DynamicOData object, its handling of the Value pseudo-property actually writes to the same XDocument in memory that all of the DynamicOData objects reference throughout the call chain.

The code in Listing 2 and the sample output shown in Figure 3 makes this fairly clear. Go back and look at them. Before changing the BluRay.Availability property, the value obtained from the Netflix service was false. After changing it, the value read by a separate DynamicOData object is reported as true. A hypothetical Save method within the DynamicOData would only need to detect these sorts of changes and use the OData protocol to update them on the server.

Accessing the Dynamic Object as an Array

When working with OData, lists of data are very common. To handle them well, you’ll want to add some functionality to your dynamic data classes. You may have noticed in Listing 3 that the DynamicOData class implemented the IEnumerable contract. This isn’t anything special required to enable dynamic typing. The code to do it is easy enough:

public IEnumerator GetEnumerator()
{
  foreach (var element in _current)
    yield return new DynamicOData(element);
}

Just as I returned each named node in TryGetMember as a new DynamicOData object to make chaining possible, the iterator shown here wraps each XElement in the _current collection as a new DynamicOData object so that all of the nice dynamic language semantics we want to apply to the XML document extend to each node. Here’s a bit of test code that uses eBay’s OData feed to find the top ten items on their site pertaining to the same movie that we queried Netflix about.

string ebayQueryFormat =
  "http://ebayodata.cloudapp.net/" +
      "Items?search={0}&$top=10";
string ebayUrl = String.Format(
  ebayQueryFormat, movieTitle);
DynamicOData ebayItems =
  new DynamicOData();
ebayItems.OnDataReady +=
  OnEbayItemsReady;
ebayItems.FetchAsync(ebayUrl);

It’s the same pattern I used for fetching data from Netflix. I’m using the same DynamicOData type that I used to query Netflix. However, the query is a bit different since eBay provides a search verb to which the search term can be assigned. Listing 7 shows the OnEbayItemsReady method that is called when the data is loaded.

The foreach loop shown in Listing 7 takes advantage of the IEnumerable implementation in my DynamicOData class. Inside that loop, since each returned item has been wrapped as a new DynamicOData instance, properties specific to the eBay OData feed like Id, Title and CurrentPrice become resolvable. Of course, if I wanted to ascribe array-like semantics directly to the DynamicOData class, I could do so by overriding TryGetIndex as follows:

public override bool TryGetIndex(
  GetIndexBinder binder, object[] indexes,
  out object result)
{
  int ndx = (int)indexes[0];
  result = new DynamicOData(
    _current.ElementAt(ndx));
  return true;
}

This is a very simplistic implementation that assumes that my indexing strategy is purely numerical. Do you see the cast operation to coerce a single integer from the array? However, any sort of indexing I need is possible. The indexes parameter of the TryGetIndex method is an object array, meaning that C# compiler will pass exactly what’s provided by the caller. There may be one index value or a dozen of them. They could be strings or integers or even complex data types. The sky’s the limit as they say, so I’m free to get as creative as I like with the way in which the index parameters are implemented.

Hopefully, the DynamicOData class I’ve shown here opens your eyes to the possibilities available to you when using the DLR. What I’ve created isn’t about dynamic languages per se. It’s true that C# and Visual Basic feels more dynamic when using a class that’s powered by the IDynamicMetaObjectProvider contract. But C# and Visual Basic are still statically-typed languages under the hood. Deferral of some binding operations until runtime gives them a feeling of being just dynamic enough to make our code more expressive than it’s ever been before. To finish up, let’s spend a bit of time discussing the performance concerns that arise from the code you’ve seen here.

Rule and Call Site Caching

The biggest concern that many developers have with dynamic programming languages is performance. The DLR goes to extraordinary measures to address that concern. I’ve touched briefly on the fact that the CallSite<T> class exists within the namespace called System.Runtime.CompilerServices. Also in that namespace are a number of other classes that perform caching at a variety of levels. Using these types, the DLR implements three major levels of caching to speed up dynamically dispatched operations:

  1. A global rule cache
  2. A local rule cache
  3. A polymorphic delegate cache

The rule caches are used to avoid spending computing resources when binding objects by type for specific call sites. If two objects of type string are passed to a dynamic method and an integer is returned, global and/or local rule caches may be updated to record that pathway to the dynamic code. This can speed up binding in future calls.

The delegate cache, which is managed within the call site object itself, is called polymorphic because the delegates stored there can take many shapes depending on code that’s encountered at runtime and the rules in the other caches used to generate them. As a runtime compiler service, the delegate cache is also sometimes referred to as inline. The reason for that term is that the expressions generated by the DLR and its binders are assembled into MSIL and Just-In-Time (JIT) compiled, just like any other .NET code. This runtime compilation happens in line with the normal flow and execution of your program. As you can imagine, turning dynamic code into compiled .NET code on the fly can make a massive, positive impact on the performance of the application.

With the downloadable source code for this article, I’ve included a second project called PythonIntegration that interfaces some C# code to IronPython. I won’t cover the application here because it’s lengthy and would require a lot more space to describe. You’ll need to download and install IronPython if you want to experiment with the PythonIntegration application, of course. What you’ll discover is the vast difference between the static-to-dynamic language interoperability of the past compared to the high performance options offered by Microsoft’s DLR. Some over-the-border operations from C# to Python, measured in tight repetition, are literally 100,000 times faster using the caching mechanisms that you get for free when using the DLR. These same caching tactics are applied when calling from C# to any other CLR-compliant language, too.

Conclusion

The DLR isn’t just about dynamic languages. It opens up a whole world of possibilities for communicating between disparate systems. As .NET’s language of languages, the DLR enables the movement of code and data with a kind of fluidity and natural expressiveness that weren’t possible beforehand. As you've seen, the language of a data model like OData can be mapped rather generically into the syntax of C# and Visual Basic using the DLR, increasing comprehension dramatically. Other call invocation systems like Java’s Remote Method Invocation (RMI) can be mapped directly into our favorite languages as well, breathing life into existing code bases and increasing their overall business value. Because the DLR can shape the code and data of any other system into .NET so gracefully, the possibilities for using it should be limited only by your imagination.