C# 4.0 has introduced the dynamic keyword. You can declare a variable as dynamic and regardless of what can be inferred at compile time, you can access any properties and call any methods and your code will still compile. Resolving of those properties and methods will be done at runtime. If at runtime, they aren't found, you'd get a runtime exception. If they are found, your code will run fine.

An Example

Consider a class called Person that has a property called Name. Consider the following piece of code:

Person p = new Person { Name = "John" };     
object o = p;     
dynamic d = o;     

On line 2, we're assigning p to an object reference o. Before C# 4.0, if you wanted to get the value of o's Name (and it does have a Name, since we know we assigned a Person object to o) you would have had to resort to reflection. With C# 4.0 however, we can use a dynamic variable like we did on line 3, and simply access the Name property on the dynamic variable. This program would compile fine, but it would require that the object assigned to d must (at runtime) have a property called Name. If it doesn't, it'll throw an exception.

So basically, we can assign a dynamic variable with any object and call properties and methods we expect it to have and it should run fine. Right? Not quite.

The Problem

The dynamic approach has one limitation – it must know the type of object it's dealing with. This isn't a problem for most cases, but it can be an issue when dealing with anonymous types. Let's get started building the project so you can see what I mean.

The Project

Create a basic .Net 4.0 console application called DynamicTest. Add a class library called ClassLibrary1 to the solution. Make class1.cs look like this:

namespace ClassLibrary1     
    public class Person     
        public string Name { get; set; }     
        public int Age { get; set; }     
    public class Repository     
        Person _person = new Person { Name = "Adam", Age = 21 };     
        public object GetPerson()     
            return _person;     
        public object GetPersonWrappedInAnonymousType()     
            return new { Person = _person };     

We have a repository that has two methods. One simply returns a person as an object while the other wraps it in an anonymous type and returns an instance of that anonymous type. Going back to the main project's Program.cs, add the following code:

class Program     
    static void Main(string[] args)     
        new Program().Run();     
    private void Run()     
        var rep = new Repository();     
        dynamic data = rep.GetPerson();     
        dynamic data2 = rep.GetPersonWrappedInAnonymousType();     

That looks simple enough. data and data2 are both dynamic variables. As such, their Name and Person.Name properties will be resolved at runtime. The program compiles fine, but when we run it, we get this:


Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'obj
ect' does not contain a definition for 'Person'
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T
0 arg0)
   at DynamicTest.Program.Run() in F:\MyTests\C#\DynamicTest\DynamicTest\Program
.cs:line 24
   at DynamicTest.Program.Main(String[] args) in F:\MyTests\C#\DynamicTest\Dynam
icTest\Program.cs:line 13
Press any key to continue . . .

How come? The call to data.Name resolved fine, but the call to data2.Person failed. The error message states that the Person property could not be found at runtime. We can obviously see by looking at the code that data2 most definitely has a Person property and that in turn has a Name property. [And if you don't trust your eyes, you can run in debug mode, set a breakpoint just after data2 is initialized and if you use the watch window to view the properties of data2, you'll see that data2 does indeed have a data2.Person property but if you type in "data2.Person" in the watch window, you'll get the same exception…magic!]. So what gives?


The reason the call to data2.Person fails is that the type information of data2 is not available at runtime. The reason it's not available is because anonymous types are not public. When the method is returning an instance of that anonymous type, it's returning a System.Object which references an instance of an anonymous type -  a type who's info isn't available to the main program. The dynamic runtime tries to find a property called Person on the object, but can't resolve it from the type information it has. As such, it throws an exception. The call to data.Name works fine since Person is a public class, that information is available and can be easily resolved.

This can affect you in any of the following cases (if not more):

1. You're returning a non-public, non-internal type using System.Object.
2. You're returning a non-public, non-internal derived type via a public Base type and accessing a property in the derived type that's not in the base type.
3. You're returning anything wrapped inside an anonymous type from a different assembly.

i.e. you need to be able to access the type info for the object at the point where its property / method is being resolved at runtime.


The solution is actually quite simple. All we have to do is open up AssemplyInfo.cs of the ClassLibrary1 project and add the following line to it:


What this does is allow the main project to "look into" the internal types of ClassLibrary1. This means the dynamic runtime can find the type information of the anonymous type being returned and data2.Person.Name resolves perfectly. Anonymous types are internal. Adding that piece of code makes the type information "visible" to our main project.


As you can see, the solution means you actually have to have control over the class library's source code for this to work. If you don't, then I guess you'd need to resort to good old fashioned reflection.


This approach can come in handy for unit testing. You would expose the internal types of the assembly under test to the tests, and as such should be able to take advantage of the dynamic functionality of C# 4.0 when evaluating results from methods that return anonymous types.



Shout it kick it on DotNetKicks.com


Questions  and comments relating to this article are welcome. Comments completely unrelated to the article and posted with the sole intention of putting your link here are not.

If you spam, your comment will not be approved, will be deleted and your IP blocked. I maintain my site almost daily and such comments – even if they pass the spam filter – will get removed as soon as possible. If this gets too tedious, I may disable comments entirely. Please don't ruin it for everybody else.