C# and Visual Basic on the WinRT API
While ostensibly an OOP-based framework, COM is very different than .NET. Prior to WinRT, COM was interface based rather than class based. This meant that it lacked many things .NET developers take for granted such as constructors and static methods. C++ Component Extensions addresses this.
WinRT’s flavor of COM uses the same metadata format used by the Common Language Runtime. This information is stored in WINMD files that show the structure, though not the implementation, of all the public classes. FXCop is used to verify that the APIs exposed by these files obey the .NET Framework Design Guidelines.
.NET has had an “API Design Board” since the very beginning. Inspired by this, the Windows Runtime will also have an API Design Board to govern it. Many of its initial members sit on the .NET board and many of its guidelines are directly lifted from the rules followed by the .NET Base Class Library.
Windows Runtime returns an HRESULT instead of throwing an exception. For well-known HRESULT values the corresponding exception is thrown, otherwise a COMException is used.
The new async/await keywords now work with WinRT’s IAsyncOperation interface just like it does with .NET’s Task object.
All Windows Runtime collection interfaces are mapped to the .NET framework equivalents. IReadOnlyList and IReadOnlyDictionary were added to .NET 4.5 in order to account for the read-only collections in WInRT.
There are two places where the WinRT and .NET APIs couldn’t be matched. WinRT steams are not directly compatible with .NET’s IO.Stream class, but an extension method called AsStream can be called to handle the conversion. WinRT also has an interface called IBuffer that cannot be easily implemented in .NET. Again, there is an extension method for translating between IBuffer and byte arrays.
C# and VB can be used to create new Windows Runtime libraries and the process is actually quite simple. In order to expose a class as a Windows Runtime Component one simply needs to set the project type to “WINMD file” and then ensure the following rules have been obeyed:
- API Signatures may only use Windows Runtime types
- Structs can only have public data fields
- Inheritance is only allowed for XAML controls, all other types must be sealed
- Only built-in generic types are supported
Since WinRT is built on top of COM you have the same problems with the dichotomy between reference counting and mark-and-sweep garbage collectors. This is mostly a problem with objects that implement a destructor to free non-memory resources. One can consider calling “Marshal.FinalReleaseComObject”, but that has its own problems.
COM style marshaling is required to make calls between .NET and native components. While this is normally insignificant, it can become an issue if the API is especially chatty.
The built-in WinRT libraries (other than XAML) are available outside of the Metro runtime environment. However, third-party WinRT libraries are not. This is a limitation of the activation framework inside WinRT, not a .NET issue.
Martin Thompson Jul 27, 2014