Sunday, September 18, 2005 - Posts

C# 3.0 Extension Methods, Ruby Mixins and Dynamic Proxies

The PDC is over and the big buzz seems to be around C# 3.0, and Linq in particular. Linq relies on a number of new features in C# 3.0 such as implicitly typed local variables, extension method, lambda functions and anonymous types. A key enabler for the Linq project is the support for generics in the CLR 2.0, and in theory you can achieve the same powerful features in C# 2.0, but you would have to write much more code to do so. The expressive query support in C# 3.0 is in a sense syntactic sugar, meaning that the compiler generates code to support the new features.

The example below shows how you can declare an anonymous type in C# 3.0
var p1=new {Name="Arthur Dent", FavoriteNumber=42 };

This is analogous with writing the following C# 1.0 code
public class AnonynousClass
{
      private string name;
      public string Name
      {
            get { return name; }
            set { name = value; }
      }
      private int favoriteNumber;
      public int FavoriteNumber
      {
            get { return favoriteNumber; }
            set { favoriteNumber = value; }
      }
}
...

AnonynousClass obj=new AnonynousClass();
obj.Name="Arthur Dent";
obj.FavoriteNumber=42; 


Infact, the code created by the C# 3.0 compiler resembles the code above. The only differences are the name of the anonymous type, that the anonymous type is a generic class (so that it can be used within a projection query) and that it overrides the method inherited from System.Object. The most important difference is a non-technical one, namely the amount of code needed to declare and use the type. Another thing to make note of is that in C# 3.0 you can use the new var keyword to have the compiler infer the type of a variable based on the expression used to initialize it.

Extension methods is the most important new feature for Linq to be useful. Extension methods are static methods in a static class with the new this modifier on the first parameter. When you import a class using the using keyword, the extension methods become available on all types thru instance method syntax. The example below show how you can declare a static class with extension methods, and import this class to extend other types you use.

public class Program
{
      static void Main(string[] args)
      {
            var s="Hello World";
            Console.WriteLine(s.WhoAmI());
      }
} 

public static class MyExtensions
{
      public static string WhoAmI(this object obj)
      {
            return obj.GetType().Name;
      }
} 


Many of the new features in C# 3.0 are well-known to developers with experience from dynamic languages such as Python or Ruby. The latter has support for mix-ins, which is a feature that resembles C# 3.0 extension methods. In Ruby you can define a mix-in on the module level. Modules in Ruby cannot include instance methods because they are not classes, but you can import modules within a class definition using the include statement. The example below shows a Ruby implementation of the previous C# 3.0 snippet.

def whoAmI?
     "#{self.type.name}"
end

s = "Hello World"
s.whoAmI?

As with C# 3.0’s var keyword, there is no need to explicitly declare the variable s as a string. Ruby will infer the type based on what you assign to it. A major difference between the two languages is that in C# type inference is done at compile-time so you cannot assign another type, such as an integer, to s after it has been declared. In Ruby type inference is done at runtime. Therefore you can do the following in a Ruby application:

s = "Hello World"
! Outputs “String”
s.whoAmI?
s=42

! Outputs “Fixnum”
s.whoAmI?

Extension methods is an elegant feature, and since you’re able to import functionally into types, it pretty much eliminates the need for multiple-inheritance.

Unfortunately, C# 3.0 won’t be generally available until Visual Studio Orcas is released. Still you have some options to achieve the same powerful feature today within both C# 1.0 and C# 2.0. As with all other new C# 3.0 features, extension methods is macro transformation that is carried out by the compiler. The compiled code for the extension method example looks like this:

[Extension]
public static class MyExtensions
{
      [Extension]
      public static string WhoAmI(object obj);
}
...
string s = "Hello World";
Console.WriteLine(MyExtensions.WhoAmI(text1));

As you can see, a call is made to the static WhoAmI method and the string s is passed as an argument. Delegating calls to a static method adds a lot of complexity to your code, and is by far as elegant as the original C# 3.0 code. If you’re not looking to extend any of the built-in types, such as System.String or System.Int32, there is another way of mimicking extension methods in both C# 1.0 and C# 2.0. You can wrap the type with a dynamic proxy. The following example shows how you can use the Castle project's Dynamic Proxy to wrap a Person class and mix-in a WhoAmI method.

class Program
{
      static void Main(string[] args)
      {
            ProxyGenerator generator=new ProxyGenerator();
            GeneratorContext context = new GeneratorContext();
            WhoAmIMixin whoAmIMixin = new WhoAmIMixin();
            context.AddMixinInstance(whoAmIMixin);
            Person myPerson=(Person) generator.CreateCustomClassProxy(typeof(Person),new WhoAmIInterceptor(),context);
            myPerson.Name=”Arthur Dent”;
            myPerson.FavoriteNumber=42;
            Console.WriteLine(((IWhoAmI)myPerson).WhoAmI());
      }
}

public class WhoAmIMixin : IWhoAmI
{
      private Type actualType;
      public Type ActualType
      {
            get { return actualType; }
            set { actualType = value; }
      }
      public string WhoAmI()
      {
            return actualType.Name;
      }
}

public interface IWhoAmI
{
      Type ActualType
      {
            get;
            set;
      }
      string WhoAmI();
}

public class WhoAmIInterceptor : StandardInterceptor
{
      protected override void PreProceed(IInvocation invocation,  params object[] args)
      {
            IWhoAmI whoAmIImpl=invocation.InvocationTarget as IWhoAmI;
            if (whoAmIImpl!=null)
            {
                  whoAmIImpl.ActualType=invocation.Proxy.GetType().BaseType;
            }
            base.PreProceed(invocation,args);
      }
}

public class Person
{
      private string name;
      public virtual string Name
      {
            get { return name; }
            set { name = value; }
      }
      private int favoriteNumber;
      public virtual int FavoriteNumber
      {
            get { return favoriteNumber; }
            set { favoriteNumber = value; }
      }
}
 

The code is much more verbose than the C# 3.0 extension method or the Ruby mix-in, but it does the same thing. The only difference to a developer programming against your Person type is that she has to cast it to the IWhoAmI interface to gain access to the WhoAmI method defined in it. While it is more cumbersome to do this in the C# versions generally available today, it is possible to extend objects with mix-ins. In a large solution there can be much to gain by applying this technique, and now that the C# 3.0 cat is out of the bag, you know what’s coming up and can align your design towards the new and elegant features that are due in a year or two.

Resources From My JavaZone Rich Internet Applications Session

On Thursday I talked about Rich Internet Applications on the JavaZone 2005 conference in Oslo. The conference had a varied agenda, with many sessions that were interesting whether you’re a pure Java developer or not. Since I spent lots of time meeting other industry peers and getting involved in allsorts of technical discussions, I didn’t catch too many sessions, but the ones I saw where great. Luckily, all the sessions from the two largest rooms will be made available as DivX recordings via the BitTorrent network in near future, so I’ll get a chance to catch up on some of the sessions I should have seen. As soon as it is available, I’ll provide a link to the .torrent file for my session as soon as it is available.

For those who attended my session, here are the resources and code snippets from my session: 

 The source code for the JavaScript implementation of the java.beans.XMLDecoder class:
function XmlDecoder(doc)
{
      this._doc=XmlDocument.create();
      this._doc.async=false;
      this._doc.loadXML(doc);
}
XmlDecoder.prototype._doc=null;
XmlDecoder.prototype._pos=0;
XmlDecoder.prototype._objectNodes=null;
XmlDecoder.prototype.readObject=function()
{
      if (this._objectNodes==null)
      {
            this._objectNodes=this._doc.getElementsByTagName("object");
            this._pos=0;
      }
      if (this._pos<this._objectNodes.length)
      {
            return this._decodeObject(this._objectNodes[this._pos++]);
      }
      return;
}
XmlDecoder.prototype._decodeObject=function(objectNode)
{
      var obj=Type.createInstance(XmlDecoder._parseClassName(objectNode.getAttribute("class")));
      var props=objectNode.getElementsByTagName("void");
      for (var i=0; i<props.length; i++)
      {
            var propName=props[i].getAttribute("property");
            var valueElm=props[i].firstChild;
            while (valueElm.nodeType!=1) valueElm=valueElm.nextSibling;
            switch (valueElm.tagName)
            {
                  case "object":
                        Type.setProperty(obj,this._decodeObject(valueElm));
                  default:
      Type.setProperty(obj,propName,Convert.fromJavaPrimitive(valueElm.firstChild.nodeValue,valueElm.tagName));
            }
      }
      return obj;            
}
XmlDecoder._parseClassName=function(qn)
{
      var qps=qn.split('.');
      return qps[qps.length-1];
} 

Finally, I want to thank everyone who attended my session. Hope you had a good time.