Create anonymous classes in C#

I’m delving into Groovy, having primarily worked with .Net due to my preference for C#’s richer feature set compared to Java (delegates, events, properties, lambdas, Iterator blocks, object literals, unsafe, PInvoke, dynamic, etc.). However, Java’s platform is undeniably robust, making a modern language like Groovy appealing for leveraging its extensive framework ecosystem.

Groovy’s “Closures” (though their semantic accuracy is debatable since they don’t always enclose external variables like true closures admit that the name is confusing) closely resemble .Net delegates. In both cases, functions aren’t treated as first-class objects; instead, the framework and compiler collaborate to encapsulate them within delegate or Closure objects.

A compelling Groovy feature is the ability to coerce Closures or Maps to implement interfaces. This elegant technique simplifies Java anonymous classes unnecessary but also reminded me of a similar Java mechanism, prompting me to explore its C# equivalent.

Despite its strengths, C# 4 lacks anonymous classes. This omission feels peculiar given the compiler’s already intricate capabilities (generating classes for closures, iterator blocks, etc.). One might assume implementing anonymous classes would be relatively straightforward. The primary rationale against them seems to be their perceived limited usefulness. In Java, anonymous classes are predominantly employed for event listeners, a scenario already elegantly addressed in C# through named and anonymous delegates. Nevertheless, as highlighted in interesting discussion, anonymous classes offer practical benefits for testing by enabling interface implementation without namespace clutter (a technique Groovyists know it well too).

So, how can we replicate this functionality in C#?

  1. We aim to instantiate objects with properties and methods without defining explicit classes (akin to JavaScript’s approach).

  2. These objects should adhere to an interface matching their properties and methods. Dynamic Proxies seem like the logical mechanism (though it’s worth noting that Java has long included this natively, while .Net still relies on third-party solutions).

Let’s address object creation first.

Anonymous Types:

1
2
3
4
var obj = new {  
  Name : "Xurde",  
  Age : 15  
};

Anonymous types prove insufficient for our purpose. They are essentially “data bags” lacking the ability to represent methods through delegates.

Dynamic Keyword and ExpandoObject:

This recent addition to the .Net-C# world provides the necessary tools. We can endow these dynamic objects with both data and code (via delegates).

Researching “make ExpandoObject implement interface” led me to insightful resources. While This brave guy bravely ventured into custom Proxy generation (and while I’m not averse to System.Reflection.Emit), I opted for the convenience of an existing DynamicProxy library, with Castle DynamicProxy being my preferred choice (and the only one I’m slightly familiar with).

Utilizing this source here, given an interface like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public interface IPrintable  
{  
 string Print();  
 string Print2(string st);  
 string Name  
 {  
  get;  
  set;  
 }  
}

we can achieve the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
dynamic ob1 = new ExpandoObject();  
ob1.Name = "Xana";  
//notice that we're using ob1 instead of "this",  turning the anonymous delegate into a closure  
ob1.Print = (Func)(() => "print: " + ob1.Name);  
ob1.Print2 = (Func)((st) => "print: " + st + ", " + ob1.Name);  
IPrintable printableProxy = ExpandoObjectProxyGenerator.GetProxy(ob1);  
//method invocation  
Console.WriteLine(printableProxy.Print());  
//get property  
Console.WriteLine(printableProxy.Name);  
    
//set property  
printableProxy.Name = "Xuan";  
Console.WriteLine(printableProxy.Name);  

Essentially, we’re employing an Interface Proxy without a designated target and implementing an IInterceptor as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 public void Intercept(IInvocation invocation)  
    {  
       Console.WriteLine(invocation.Method.Name);  
  if (invocation.Method.Name.StartsWith("get\_"))  
  //reading a property  
  {  
   string propName = invocation.Method.Name.Split(new char\[\]{'\_'})\[1\];  
   invocation.ReturnValue = ((IDictionary)(this.target))\[propName\];  
  }  
  else if (invocation.Method.Name.StartsWith("set\_"))  
  //setting a property  
  {  
   string propName = invocation.Method.Name.Split(new char\[\]{'\_'})\[1\];  
   ((IDictionary)(this.target))\[propName\] = invocation.Arguments\[0\];  
  }  
  else  
  //method invocation  
   invocation.ReturnValue = ((Delegate)(((IDictionary)(this.target))\[invocation.Method.Name\])).DynamicInvoke(invocation.Arguments); 

The key distinction to handle is between accessing interface methods and interface properties. For property access (get/set), Castle’s Invocation.Method will reference the get_[propertyName] or set_[propertyName] methods automatically generated by the C# compiler.

This exploration deepened my understanding of ExpandoObjects (which I admit I hadn’t used extensively before), with this article proving particularly helpful. ExpandoObjects offer a compelling way to emulate the dynamic expansion capabilities of Python or JavaScript objects. However, a notable difference arises when accessing members using string names. What’s effortless in JavaScript (myPerson["age"]) becomes more verbose in C#:

1
((IDictionary)myPerson)["Age"];

Although ExpandoObject implements IDictionary, it curiously relies on explicit rather than implicit interface implementation, necessitating the cast. This verbosity is further amplified for method invocations:

1
((Func)((IDictionary)myPerson)["Print"])(); 

Here, an additional cast to a compatible delegate type is required.

Licensed under CC BY-NC-SA 4.0
Last updated on Jul 09, 2024 08:36 +0100