ESAPI is a great tool for writing plug-in scripts that extend the functionality of Eclipse. But it's not perfect. Sometimes we need a feature that's not in ESAPI (and perhaps should've been). Of course, we can ask the ESAPI team to add the feature, but it may take months until the next release. We need the feature now.
For example, the PlanSetup and PlanSum classes, both of which derive from PlanningItem, have the StructureSet property. But PlanningItem does not. This makes working with a PlanningItem reference difficult (assuming we're interesting in its structure set). To get a PlanningItem's structure set, we need to figure out whether it's a PlanSetup or PlanSum, convert it to its actual type, and then call the StructureSet property on that type.
To "fix" ESAPI, we can use extension methods. Extension methods allow us to add methods to any type without changing the definition of that type. Extension methods are defined as static methods in a static class (or classes), but they are called as if they belonged to the type.
Going back to our StructureSet example, we'll define an extension method called GetStructureSet. (Unfortunately, there's no such thing extension properties, at least not yet.) We'll also define an extension method called GetCourse because the Course property is also independently defined in PlanSetup and PlanSum but not in PlanningItem. Here's the code:
public static class Extensions
{
public static StructureSet GetStructureSet(this PlanningItem planningItem)
{
if (planningItem is PlanSetup)
{
return ((PlanSetup)planningItem).StructureSet;
}
else
{
return ((PlanSum)planningItem).StructureSet;
}
}
public static Course GetCourse(this PlanningItem planningItem)
{
if (planningItem is PlanSetup)
{
return ((PlanSetup)planningItem).Course;
}
else
{
return ((PlanSum)planningItem).Course;
}
}
}
You can call the class whatever you want, but it must be static. Each extension method must also be static and its first parameter must be the type you're extending. Also, notice that the this keyword must appear before the first parameter. To use the extension methods, just call them as if they belonged to the type:
// Get the structure set of the planning item
var structureSet = planningItem.GetStructureSet();
// Get the patient having the planning item
var patient = planningItem.GetCourse().Patient;
Of course, extension methods don't have to be this simple. If you wanted to get the leaf widths of the MLC, which ESAPI doesn't provide, you can write an extension method for the ControlPoint class that goes into the ARIA database, obtains the leaf widths, and returns them.
Be careful when using extension methods. Extension methods tightly couple your code with code that you cannot change. It's possible that a future change in the API you're extending causes your extension methods to break.
Comments