Metro .NET Framework Profile (“Windows Tailored”)
The amount of confusion generated by the first two keynotes at BUILD was immense. The blogosphere and Twitter were brimming with bold rumors of the “.NET is dead” kin. I even heard someone discuss seriously the possibility that C# Metro apps will be compiled directly to native WinRT bindings, bypassing IL and JIT altogether, so that clr.dll won’t even be loaded.
Even though I disproved these rumors two days ago, it was still great to hear Krzysztof Cwalina explain in detail how .NET remains a fully-featured framework for developing Metro applications in C# and VB.NET. As you may have heard or noticed, not every .NET API is available to Metro applications – and the subset of APIs available to Metro applications is called the “Windows Tailored” or Metro profile.
Even before Metro, .NET had numerous target profiles – the Silverlight profile, the Windows Phone 7 profile, the .NET Client profile, and of course the full profile. The way profiles are implemented is a compiler trick. Visual Studio ships with a bunch of reference assemblies that you can find (on a default install) under C:\Program Files\Reference Assemblies\Microsoft\Framework. These assemblies contain only metadata and no executable code – indeed, they are not necessary at runtime because when your application runs, .NET assemblies are loaded from the GAC. To project only a part of the available APIs from the implementation assembly, the reference assembly simply omits whatever namespace, types, or methods that are not included in the profile.
Clearly, there are ways to circumvent this mechanism, such as binding directly to the GAC assemblies instead of using the Visual Studio-provided references. Another option is to use reflection at runtime. These are valid possibilities – with the minor setback that your application will not pass Windows Store certification if you use unsupported APIs. (This idea, of course, is not new, and has been exercised by Apple in iOS apps for quite some time.)
The same idea exactly is used for the Metro profile. It executes at runtime using the same assemblies as the full desktop CLR, but only a portion of it is available to Metro applications. What kinds of APIs were removed?
- Irrelevant APIs were removed – think ASP.NET, WPF, Console access.
- Obsolete and dangerous APIs were removed.
- Duplicate APIs were removed.
- Windows API wrappers were removed, in favor of the WinRT types.
- Badly designed APIs were removed.
Specifically, the following APIs that are not part of the Metro profile you are most likely to miss:
- System.Data – removed entirely. There is an OData component, but no LINQ to SQL or anything of that sort.
- Remoting – removed entirely.
- AppDomains – removed entirely. There is only one AppDomain in each Metro application process.
- Reflection.Emit – removed entirely.
- Private reflection – you cannot invoke private methods, internal methods on another assembly, access private members and so on. (Frankly, I am not so upset about this change because I’ve grown sick of “clever” solutions using some undocumented private member which breaks in a year or two.)
- System.Thread – must use Task.Run instead for all threading purposes. (Creating a new thread is roughly equivalent to creating a task with TaskCreationOptions.LongRunning.)
What kinds of APIs are included in the profile, or will require porting to use the profile?
- HTTP client stack is included.
- XML (through XML LINQ mostly) is included.
- Serialization is included (DCS).
- MEF is included.
- WCF client stack is included.
The end result is a very slim subset of the .NET framework, with only 15 implementation assemblies and ~1000 types spanning 60 namespaces. (This does not include the WinRT APIs and the Windows.UI.Xaml stack.)
Obviously, one of the reasons the resulting framework is so slim is that so much is provided by WinRT. Life has not just become easier – quite the opposite, because you have to go and learn WinRT. However, the interop story with WinRT is incredible – or rather, completely transparent – due to the brilliant type mappings from the WinRT type system to managed languages. (Quite possibly the most incredible automatic language projection is the way WinRT operations are projected to .NET Tasks and JavaScript promises.)