Tuesday, June 22, 2004

Metaclass in C#

I'm writing a class library and have to implement a feature close to XML serialization. The problem is I am not that guy who declares the scheme for serialized data. And this scheme may be expanded and extended in the future and certainly I wish to reuse the code. The scheme is designed such that there is no common algorithm to determine classname for object represented with an element. The classes are arranged in groups. Every group has its own algorithm to determine class or subgroup to which the obect belongs. If the algorithm detects only a subgroup then it calls to corresponding algorithm of that group.

For example, we have four classes B, C, E, F arranged in two groups A and D. Group D contains classes E and F, while A contains classes B and C and gourp D. I have defined the groups as highlevel classes in the hierarhy, while leaves are actual classes.

  • A
    • B
    • C
    • D
      • E
      • F

In XML objects look like

<B>B instance </B>
<C>C instance</C>
<D Type=”E”></D>
<D Type=”F”></D>

Every highlevel class has static method for the detection algorithm. I use reflection to obtain the method and transfer control to it. But I’d like to solve this task in the following way.

class AClass : Type
{
object CreateInstance( XmlElement e )
{
AClass C = Detect( e );
return C.InvokeMember( CreateInstance, new object[]{e} );
}
virtual AClass Detect( XmlElement e )
{
return this;
}
}
class DClass : AClass
{
override AClass Detect( XmlElement e )
{
AClass C = (AClass) Type.GetType( “MyNamespace.GroupA.GroupD.” + e.GetAttribute(“Type”) );
return C.Detect(e);
}
}
[Metaclass(typeof(AClass))]
abstract class A
{
A( XmlElement e ){...}
}
class B : A {...}
class C : A {...}
[Metaclass(typeof(DClass))]
class D : A{...}
namespace GroupD{
[Metaclass(typeof(AClass))]
class E : D {...}
[Metaclass(typeof(AClass))]
class F: D {...}
}

The loading object from XMl would look like

XmlElement e = (XmlElement) someXmlDoc.SelectSingleNode( someXPath );
AClass C = (AClass) Type.GetType( “MyNamespace.GroupA.” + e.Name );
A a =(A) C.CreateInstance( e );

The only new thig is MetaclassAttribute wich provides metaclass for the class being declared.

Certaily I could create some helper objects, containig detection methods. But this approach woul require creating of instances of those detection classes. Why should I instantiate new objects while .NET framework already created objects for the classes? I think the class objects should carry all the information on classes they define. The information could include some progrmmer-defined items. C# has already static memrebs. They in fact are pieces of such programmer's data on the class. MetaclassAttribute will generalize this feature.

We have run-time type information provided by .NET framework. Then we should use this information, because it's too costly to handle it for nothing.

Imagine a plug-in anabled application. It includes a plug-in management code. But the only thing a plug-in does was providing a managed class to the application. We use classes to simplify object management. But when classes became objects themselves we could use the same tool to simplify managing classes.

Another feature is the possibility to restrict method parameters of type Type to a specific set of classes.