Windows Runtime with C++/C#: Anatomy of a WinRT Class

December 30, 2012

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):

public ref class Book sealed {

public:

    Book(Platform::String^ name, int pageCount);

    Book(Platform::String^ name);

    virtual ~Book();

 

    property Platform::String^ Name;

    property Platform::String^ Author;

    property int PageCount;

 

    Platform::String^ ReadPage(int number);

 

    static property int BookCount {

        int get() { return _bookCount; }

    }

 

 

private:

    static int _bookCount;

};

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:

SNAGHTML53239df

We may expect to find just a Book class, but we find much more. Opening the Book class reveals the following:

SNAGHTML5342102

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:

SNAGHTML56b91c0

What about the constructors? These are part of the __IBookFactory interface:

SNAGHTML56c6f71

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:

SNAGHTML57def1b

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:

public Book(string name, int pageCount) {

    Name = name;

    PageCount = pageCount;

    BookCount++;

}

 

public Book(string name)

    : this(name, 0) {

}

 

~Book() {

    BookCount--;

}

 

public string Name { get; set; }

public string Author { get; set; }

public int PageCount { get; set; }

public static int BookCount { get; private set; }

 

public string ReadPage(int page) {

    return "sample page";

}

 

public void Dispose() {

    GC.SuppressFinalize(this);

    BookCount--;

}

    }

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:

SNAGHTML582f3fb

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.

Conclusion

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.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*