The Windows Runtime (WinRT) is based on COM (I referred to it in the past as a “better COM”), which means every method and property must be part of an interface. Also, COM does not support static members (only instance members) and does not easily support parameterized constructors. Inheritance is again an issue in classic COM – the closest thing is COM aggregation, and that’s not really inheritance in the usual sense of the word.
Using C++/CX or a .NET language allows creating WinRT types that support methods, properties, constructors and static members, and even events (another feature that is not directly supported by COM). We can even have inheritance, although currently it’s limited to the Windows::UI::Xaml::DependencyObject class (or any of its derivatives).
How does all this works in WinRT?
Let’s create a WinRT class, first in C++/CX and then in C# and take a look at the metadata for hints on the actual implementation. Here’s a Book class written in C++/CX that uses some WinRT features (to create this yourself, create a Windows Runtime Component project in Visual Studio 2012 under the C++/Windows Store node):
There are two constructors, a method, three properties, a static read only property and a destructor. How does that translate to WinRT?
Let’s open the resulting WINMD file in ILDASM:
We may expect to find just a Book class, but we find much more. Opening the Book class reveals the following:
The metadata seams mostly what we expect: the ReadPage method, the two constructors and the properties, with their get/set methods. The odd thing is the Close method that’s in there – our original Book class has no such method. This method is part of the WIndows::Foundation::IClosable interface that’s implemented by our Book class. Where did that come from? You guessed it – that’s the result of the destructor.
The other interface implemented by Book is __IBookPublicNonVirtuals – this is “the” interface from which the instance methods and properties originate:
What about the constructors? These are part of the __IBookFactory interface:
There are two CreateInstance methods here, one for each defined constructor. Notice that Book does not implement that interface. Instead, it’s implemented by the activation factory (class factory) of the Book. We can get a hint of this by looking at the attributes defined by Book, specifically, the Windows::Foundation::Metadata::Activatable attribute:
.custom instance void [Windows]Windows.Foundation.Metadata.ActivatableAttribute::.ctor(class [mscorlib]System.Type,
uint32) = ( 01 00 19 42 6F 6F 6B 4C 69 62 43 50 50 2E 5F 5F // …BookLibCPP.__
49 42 6F 6F 6B 46 61 63 74 6F 72 79 01 00 00 00 // IBookFactory….
00 00 )
Where is the activation factory? It’s implemented by the C++/CX compiler – this is one of the things that makes C++/CX easier to use than straight COM.
The last piece of the puzzle is the static members. These are defined by the __IBookStatics interface:
We can see the BookCount read only property (the only defined static member in the Book class).
Again, Book does not implement that interface; instead, it’s implemented by the activation factory (yes, again). This is how Microsoft solved the problem of static members; the activation factory is a natural singleton, which is perfect for storing static members.
WinRT Component in C#
Let’s try the same experiment with C#. We’ll create a Windows Runtime Component project with C# and create a similar Book class like so:
The implementation itself is unimportant; what is important is the resulting metadata, which makes visible the consumable parts of the Book class from any WinRT projection. Here’s the WINMD file open in ILDASM:
Note the similarities to the C++/CX metadata. Here’s the equivalence (C# on the left)
Book —–> Book
IBookClass —–> __IBookPublicNonVirtuals
IBookFactory —–> __IBookFactory
IBookStatic ——> __IBookStatic
The only new class is <CLR>Book, which is the actual .NET type that wraps the WinRT type.
The interface names of course are unimportant, as their identified via their interface IDs (which are GUIDs).
One thing to note that the IDisposable .NET interface is mapped to the IClosable WinRT interface.
So there you have it; WinRT under the covers. I haven’t shown events nor inheritance, but I’ll leave that as an exercise to the interested reader.
With the language projections, WinRT is a better COM.