home screen

Search



Number Of Result : 0

Result :


Wednesday, October 29, 2008

C# "dynamic," Part II

Yesterday, I made an attempt to introduce the C# dynamic feature by

describing what change there has been to the language, what scenarios we hope to affect by that change, and some overview of what dynamic operations look like in C# 4 as it stands in the preview distributed at PDC 2008.

One thing that I did not mention was this: that the language changes are entirely focused around consumption of dynamic types, not definition of those types. This is not to say that you cannot define dynamic types--just that the C# language has not change in any way so as to provide you a shortcut. We have not added a "method_missing," nor are any of the regular types you define in C# capable of somehow dynamically acquiring properties. And you can't say something like "dynamic class C" to define such a class.

If you want to define a new type that accepts dynamic operations, then it's easy to do so, and you don't even need C# 4. You just implement IDynamicObject, which is the interface that tells the DLR, "I know how to dispatch operations on myself." It's a simple interface, in the spirit of IQueryable, with a single method that returns a "MetaObject" to do the real heavy lifting.

I want to make clear at this point that I am about to provide an example of how to use the DLR, but that I am only doing so in order to demonstrate how these objects play with the C# 4 language features. There are other blogs that are certainly better sources for information about the DLR.

So, here's an implementation:

public class MyDynamicObject : IDynamicObject 
{   
 public MetaObject GetMetaObject(Expression parameter)  
 {     
  return new MyMetaObject(parameter);   
 
}

Simple enough! Here's the MyMetaObject definition. The MetaObject "knows how" to respond to a variety of actions including method calls, property sets/gets, etc. I'll just handle those (no best practices here; this is a minimal implementation):

public class MyMetaObject : MetaObject 
{   
 public MyMetaObject(Expression parameter)     : base(parameter, Restrictions.Empty)   {   }      
 public override MetaObject Call(CallAction action, MetaObject[] args)   
 {     
  Console.WriteLine("Call of method {0}", action.Name);     
  return this;   
 }    
 public override MetaObject SetMember(SetMemberAction action, MetaObject[] args)   
 {     
  Console.WriteLine("SetMember of property {0}", action.Name);     
  return this;   
 }    
 public override MetaObject GetMember(GetMemberAction action, MetaObject[] args)   
 {     
  Console.WriteLine("GetMember of property {0}", action.Name);     
  return this;   
 
}

This is exactly what, say, IronPython might do to implement the dictionary lookup that it needs to do for its members. And when I say "exactly," I mean "sort of" because of course IronPython's implementation is considerably more complex and robust. But this gets the job done. Suppose I want to now use C# to invoke these things using the new syntax. That's the easy part! Check this out:

public class Program 
{   
 static void Main(string[] args)   
 {     
  dynamic d = new MyDynamicObject();      
  d.P3 = d.M1(d.P1, d.M2(d.P2));   
 
}

So I take my MyDynamicObject that I defined above, and then I get a few properties, call a few methods, and set a property for good measure. If you compile this, you get the following output:

GetMember of property P1 GetMember of property P2 Call of method M2 Call of method M1 SetMember of property P3

I think that's pretty cool.

Next time I'll talk more about the dynamic type again, in the C# language, and how it behaves. I just wanted to take a little diversion to clear up the fact that we've really done a lot of cool work on the consumption side, and your code ought to look better for it when you're consuming these things. If you're defining them, then you're in DLR-land, and you might even be writing in python or ruby or some other language. I'll provide pointers to those issues as I get them.


Track URL : http://blogs.msdn.com/cburrows/archive/2008/10/28/c-dynamic-part-ii.aspx


No comments: