Many developers tend to look at Windows 8 as a completely new platform and even question whether it heralded the imminent demise of managed code. After spending many months digging into the Windows Runtime (WinRT), Metro style or “tailored” applications, and exploring how they related to the .NET Framework, I’ve come to the conclusion that the two work very closely together and in fact are engineered to integrate. That means good news for managed developers. The .NET Framework 4.5 is very much “Metro-aware” while the Windows Runtime knows how to shake hands with the CLR. The purpose of this post is to elaborate on this a bit more than what I covered in my Portable Class Library series.
The first thing to note is that WinRT components, regardless of what language they were written in, share the same metadata format as .NET Framework assemblies. This is what allows you to navigate to the metadata folder at c:\windows\system32\WinMetadata and be able to use ildasm.exe to expose the definitions of WinRT components that are part of the Windows 8 operating system. The standard is documented as ECMA-335 and you can check this link to learn more.
As part of this metadata, types and assemblies can be tagged with a new Intermediate Language (IL) keyword called windowsruntime. This keyword tags the type as a WinRT component. The .NET Framework uses this to know when to marshal parameters because the WinRT type system is not the same as the one supported by the CLR. Fortunately, this is supported “under the covers” as you’ll see in the next section. When an assembly is tagged with the keyword, it instructs the .NET Framework to use a special APIs like the one called RoResolveNamespace to load references. This is a way that all supported WinRT languages can access underlying components.
As I mentioned, the .NET Framework does some magic with type conversion. This happens in both directions (calls into and values received from WinRT components). This is not new – this has been supported for awhile and you can see a list of Default Marshaling for Value Types in the MSDN documentation. A System.Int32 becomes a ELEMENT_TYPE_I4 and vice versa. These are what are referred to as “fundamental types.”
In addition, however, the CLR performs implicit mapping to more complex types. If you’ve been doing any Windows 8 development, you are probably familiar with conversions that look like this:
Windows.Foundation.Collections.IVector<T> <= => System.Collections.Generic.IList<T>
You can read the list of WinRT collection ty
pes, then drill into the detail to see the corresponding .NET map.
Here is a list of commonly mapped types:
|Windows Runtime||.NET Framework|
|IMap<K, V>||IDictionary<TKey, TValue>|
|IMapView<K, V>||IReadOnlyDictionary<TKey, TValue>|
There are other mapped types that you may not be as familiar with, such as the map from a Windows.Foundation.Uri to a System.Uri.While this is done “automatically” it does have side effects. The WinRT Uri does not support anything but absolute Uris, so any attempt to pass a relative Uri into a WinRT component will fail.
Any other types are projected automatically without conversion. A good example of this is the built-in XAML controls for building Metro applications. Windows.UI.Xaml.Controls.Button appears as a CLR class to your .NET code, but it also appears as a C++ class to developers using the C++ option. There is no map or conversion, the type remains the same but the projection provides all of the plumbing necessary for it to act and feel like a type native to the environment you are working in. Any necessary wrappers are created behind the scenes – you’ll learn more about that later.
Because special types can have side effects, it’s important to know what they are and what restrictions exist. Here is a short list:
s, you should be prepared to convert the value to local time before passing it to a WinRT component and back from local time to the target time zone when you receive values back.
In addition, it’s important to note some WinRT types and how they impact the CLR. Understanding these types is more important if you plan to write WinRT components in C++ for consumption by the .NET Framework – otherwise most of this happens behind the scenes for you.
In the CLR, managed events can have multiple delegates assigned and removed. Removing an event is as simply as using the operator to remove it and passing the delegate that handles the event callbacks. In WinRT, the event system is token-based. When you add a delegate to handle an event, you receive a unique token. To remove your delegate from the event, you call a method to remove and pass in the token, not the delegate.
Events are mapped between the CLR and WinRT by the compiler. If you decompile your code you will see this in action. The CLR uses the helper classes:
The compiler will emit code that maps the events through these classes. The classes will maintain the dictionary of tokens and delegates, so you can code your familiar remove operation and have it automatically pass the correct token behind the scenes.
For the most part, you don’t have to worry about any of the magic happening behind the scenes because it is done for you. However, the purpose of this was to show how much thought and engineering went into actually working with both .NET and WinRT to ensure the two could work closely together. This to me is evidence that .NET is not a second-rate citizen in Windows 8, but an important factor that was carefully considered as part of the overall strategy to create a flexible new platform with reach.