Thoughts on Software by Andrew Davey
 Thursday, July 26, 2007
C# Code Generation

I came across http://www.codeplex.com/csparser today. This parser takes C# source code and produces in memory object tree representing the code. This object tree can be modified and the resulting source code extracted back out as a string.

I have been thinking about ways to remove the mindless plumbing code I have to write when implementing a Model-View-Presenter architectural system. For example, I define an interface for my Model. I then make a Model class that implements the Model interface. The slow bit here is implementing all the properties with fields, defining events and the OnSomeEventHappened(Args) methods to safely raise them.

Whilst there are tools that will probably do this plumbing for me, they have one flaw. I don't want to even read, let alone write, that boiler-plate code! It does not help me understand what it going on. The interface contains all the important details. I basically want the compiler to generate it for me.

C# has no syntactic macro system (unlike Boo and Nemerle) so I'm stuck with my current XML/XSLT based code generator. Whilst this is usable, it really means I'm no longer coding in C#, but rather long-winded XML. The context switch there is a bit annoying.

With the CS Parser I will be able to the following:
Write a Visual Studio Custom Tool (like my XML/XSLT code generator) that takes C# code file of an interface and generates an implementing class. This is done by parsing the interface definition, then looping through members and creating a new class definition accordingly.
If the class already partially exists I can allow the user to type specific members they need to implement in a non-standard way and not generate these automatically.
The output of the Custom Tool (new C# code) is then compiled automatically as part of the Visual Studio build process.

For example:

public interface IModel
{
  int Amount { get; set; }
  event EventHandler AmountChanged;
  void Load();
}

Generates into:

public partial class Model : IModel
{
  int _amount;
  public int Amount
  {
    get { return _amount; }
    set
    {
      _amount = value;
      OnAmountChanged();
    }
  }
  public event EventHandler AmountChanged;
  protected virtual void OnAmountChanged(EventArgs e)
  {
    EventHandler handler = AmountChanged;
    if (handler != null)
       handler(this, e);
  }
}

Leaving the developer just to write the Load method.

I'm wondering about generalising this a bit. Using magic attributes that are picked up by a tool (much like syntactic macro attributes in Nemerle) to invoke specific actions.

[AutoImplement(IModel)]
public class Model : IModel
{
   public void Load() { ... }
}

Fun times ahead!!


Thursday, July 26, 2007 4:47:58 PM (GMT Standard Time, UTC+00:00)  #    Comments [1]  

Tuesday, May 20, 2008 4:59:42 PM (GMT Standard Time, UTC+00:00)
Reference: Very helpful, thanks!!
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):