Alan Cameron Wills - Domain Specific Languages

Models, domain-specific languages, code generation, ....

partial classes

We use partial classes a lot in the DSL Tools. We need them to help compose code that’s generated from different places, and generated with handwritten code.

If you’re not familiar with it, a partial class definition is just a set of methods, properties etc that gets combined with another partial definition at link time, to form a complete class. The parts can be in different source files, which makes it easier to manage them separately: different generators can output to different files. So in the DSL Tools Use Case template, there are two generated files Designer.dsldm.cs and Shapes.cs that each contain aspects of every shape you have defined in your language. You can add a separate file with your own definitions.

There is a particularly useful pattern for providing a hook for optional manually defined features.  Each generated class – let’s take Container.cs in the Use Case template – has a framework superclass in which default values are defined as overridable properties. For example, HasBackgroundGradient is defined in the framework superclass OutlinedShape. This enables you to override HasBackGroundGradient if you wish in a partial Container class, but to leave it to default to the OutlinedShape value otherwise.



partial class ContainerShape : Microsoft.VisualStudio.Modeling.Utilities.OutlinedShape {…


 public class OutlinedShape { protected virtual bool HasBackgroundGradient { get { return true; } } …

Optional manual override:

public class OutlinedShape { protected override bool HasBackgroundGradient { get { return false; } } …

It isn’t as sophisticated or flexible as delegation or aspect weaving, but does the trick.

Unfortunately, it only works for program code! If we’re generating tables, configuration files, or reports, we need a way of merging them together. One way is to get the generator to read the file and only replace particular bits, corresponding to one view. Another, cleaner, way is to have each source generating to a separate file, and then weave them together in a final step.