Integration of the Classbox Concept in the .NET Framework |
[Background] [Classboxes] [Example] [Classboxes in C#] [Backend] [Summary] [Publications] [Contact]
Nowadays, many software systems are built using the object-oriented
software development approach. However, as many people know, the
object-oriented approach can be troublesome when it comes to the
extension of a program. More precisely, the mainstream
object-oriented approach provides only limited support for
horizontal or vertical addition to a class hierarchy.
While in general it is always possible to add (vertically) new classes to a system, existing classes can only be extended with new, orthogonal behavior (horizontally) in an often non-object-oriented style, that is, by breaking the object-oriented encapsulation property (e.g., the Visitor pattern). Such extensions are awkward at best, and error-prone at worst. Furthermore, the inheritance relationships in mainstream object-oriented languages are not powerful enough to capture many useful forms of incremental modifications. There are several approaches to resolve this problem. One of them would be the classbox concept. |
Classboxes
are a new module system for object-oriented languages that defines
a packaging and scoping mechanism for controlling the visibility of
class extensions to portions of object-oriented systems:
How can we denote change?
![]() Class extensions are used to add or refine features of existing classes in a namespace. How can we manage change?
![]() Class extensions are only visible in the namespace in which they are defined. |
![]()
|
In our model, a classbox is represented as a namespace in C#. To
implement the classbox concept, we add two new syntactic
facilites:
The syntax for extension-declaration: extension-declaration: extension identifier class-body ;optThe syntax for using-extension-directive: using-extension-directive: using identifier = type-name extension-application extension-application: includes opt refinements opt includes: include type-list; refinements: append type-list;
ColorCB and TraceCB:namespace ColorCB { using System.Drawing; using Point = Original.Point append Color; using LinearBoundedPoint = LinearCB.LinearBoundedPoint; extension Color { private Color color; public Color Color { get{ return color; } set{ color = value; } } } } namespace TraceCB { using Point = ColorCB.Point include TraceMoveBy; using LinearBoundedPoint = LinearCB.LinearBoundedPoint; extension TraceMoveBy { public void MoveBy( int dx, int dy ) { Console.WriteLine( "MoveBy: {0}, {1}", new object[] { dx, dy } ); base.MoveBy( dx, dy ); } } } The front-end translates the locally refined class Point in ColorCB and TraceCB into a new class Point as shown below:
public class Point : OriginalCB.Point { private Color color; public new virtual Color Color { get { return color; } set { color = value; } } // required constructor(s) public Point( int ix, int iy ) : base( ix, iy ) { } } public class Point : ColorCB.Point { public override void MoveBy( int dx, int dy ) { Console.WriteLine( "MoveBy: {0}, {1}", new object[] { dx, dy } ); base.MoveBy( dx, dy ); } // required constructor(s) public Point( int ix, int iy ) : base( ix, iy ) { } } Remaining Issues
Our solution: metadata transformations to rewire the inheritance chain of classes. |
The Backend process of the C# implementation of the classboxes
concept utilizes the Common Language Infrastructure (CLI) of the
.NET framework. A key aspect to our approach is that a growing
number of modern programming systems compile program code into a
platform-independent representation that is executed in a virtual
execution system like CLI that use both Intermediate Language (IL)
bytecode and metadata.
Our approach allows us to read assembly files that contain the corresponding metadata, transform it based on any local refinements that we define in the corresponding classbox, and write it back as transformed metadata into new assembly files of the corresponding classbox. Why do we have to transform this metadata? This is because metadata contains the structure of classes and their underlying class hierarchies that we want to extend in the classbox module. So, after the compilation process (which produces this metadata information), we carry out so-called code instrumentation to manipulate the metadata, and afterwards, we write the transformed metadata back into the assembly. Overview of the Metadata StructureThe result of compiling classbox OriginalCB into the CLI is the assembly OriginalCB.dll that has the following layout:
![]() Given above is an example of how classbox OriginalCB is represented in the metadata that is contained in the assembly OriginalCB.dll. Imported Token Types:
Rewiring of the Inheritance GraphBy rewiring the metadata we create the structure of a classbox and integrate all locally refined classes into their corresponding class hierarchy.
![]() Required Metadata Transformations
The Assembly Structure of ColorCB![]() |
Classboxes provide a feasible solution to the problem of
controlling the visibility of change in object-oriented systems
without breaking existing applications, as they strictly limit
both its scope and impact to clients of the extending
classbox. Consequently, classboxes can significantly reduce the
risk for introducing design and implementation anomalies due to
the need to adapt a software system to changing requirements.
We have developed an approach to augment C#, an industrial-strength programming language, with the classbox concept. In our model, classboxes are represented by C# namespaces and the corresponding operations are defined using a small extension to the C# language. The integration of this extension is achieved by means of code instrumentation to rewire metadata type declarations in assemblies. This approach allows us to imprint the structure of a classbox in metadata, resulting in a seamless integration of classbox concept into the .NET framework. Next Steps
|
|
|