Monday, February 9, 2009

Extending code generation with partial classes and inheritance

One of the bigger problems with Code Generation is changeability. Generated code should never be modified. Anything that you modify on a generated class will be lost when you run the generation again. The problem is that if you need to extend/alter your generated class, you cannot do it without taking it out of the generation process (which is sometimes acceptable, but mostly not).

Gladly, C# 2.0 introduced the concept of “partial” classes a long time ago. You must have seen it. When you create a new Windows Form, you get two classes; one is for the generated code in InitializeComponents and the other is for you to use. If your architecture is similar to this case, you can do the same: generate a partial class with all the generated code and have a partial class with any extra code the developer may need to add.

Most of the times, though, the need is to replace the generated code with something completely different in some specific cases. That is, almost all the generated code is ok, but one or two methods in one or two classes need to be replaced. In this case, you can use a different approach: the “double-derived” pattern introduced in Microsoft DSL. It works like this:

When you generate code, you generate 2 classes instead of one. The first class (MyGeneratedClassBase) will have all the methods implemented and marked as virtual. The second class (MyGeneratedClass) will inherit from the first class, and will be marked as partial. This will be transparent to whoever needs to use the class and it will allow you to change the implementation of the methods you need via overriding. If you regenerate the classes afterwards, nothing breaks.

Let me show you in an example. Say you are generating classes from a database. You generate each table with properties for the fields and CRUD methods. Something like this:

public class Customer
{

public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public int Create()
{
//some implementation
}

public void Update()
{
//some implementation
}

public void Delete()
{
//some implementation
}

public void Retrieve()
{
//some implementation
}

}


Now, let’s suppose you need to override the Delete method so you will not be allowed to delete customers (let’s assume this makes sense just for the sample). If you change the generated class directly, you’ll loose your changes when the class is regenerated. In the double-derived pattern, you’ll have this instead:



public class CustomerBase
{

public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }

public virtual int Create()
{
//some implementation
}

public virtual void Update()
{
//some implementation
}

public virtual void Delete()
{
//some implementation
}

public virtual void Retrieve()
{
//some implementation
}

}

public partial class Customer : CustomerBase
{
}


A developer will use the Customer class as before, but now you can create a new partial class for Customer, overriding the Delete method like this:



public partial class Customer
{
public override void Delete()
{
}
}


Notice that this class is not the same as the generated class, but a new partial class created by you. Also notice that you cannot change the return value for the method. You can change the parameters of the method by creating a new overload for it.



This way you’ll be able to change standard implementation on a need-to-change basis while still using your code generation for most of your code. Also, you can regenerate on every build if needed.

1 comment: