Windows 8 as introduced at Build is an exciting release as
it has important updates to how Microsoft envisions users will
interact with their computers, to a fresh new user interface
to a new programming model and a lot more.
If you build software for end-users, you
should watch
Jensen Harris discuss the Metro principles in Windows 8.
I find myself wanting to spend time using Windows 8.
But the purpose of this post is to share what I learned at
the conference specifically about WinRT and .NET.
The Basics
Microsoft is using the launch of Windows 8 as an
opportunity to fix long-standing problems with Windows, bring
a new user interface, and enable a safe AppStore model for
Windows.
To do this, they have created a third implementation of the
XAML-based UI system. Unlike WPF which was exposed only to
the .NET world and Silverlight which was only exposed to the
browser, this new implementation is available to C++
developers, HTML/Javascript developers and also .NET
developers.
.NET developers are very familiar with P/Invoke and COM
Interop. Those are two technologies that allow a .NET
developer to consume an external component, for example, this
is how you would use the libc "system (const char *)" API
from C#:
[DllImport ("libc")]
void system (string command);
[...]
system ("ls -l /");
We have used P/Invoke extensively in the Mono world to
create bindings to native libraries. Gtk# binds the Gtk+
API, MonoMac binds the Cocoa API, Qyoto binds the Qt API and
hundred other bindings wrap other libraries that are exposed
to C# as object-oriented libraries.
COM Interop allows using C or C++ APIs directly from C# by
importing the COM type libraries and having the runtime
provide the necessary glue. This is how Mono talked with
OpenOffice (which is based on COM), or how Mono talks to
VirtualBox (which has an XPCOM based API).
There are many ways of creating bindings for a native
library, but doing it by hand is bound to be both tedious and
error prone. So everyone has adopted some form of "contract"
that states what the API is, and the binding author uses this
contract to create their language binding.
WinRT
WinRT is a new set of APIs that have the following properties:
- It implements the new Metro look.
- Has a simple UI programming model for Windows
developers (You do not need to learn Win32, what an
HDC, WndProc or LPARAM is).
- It exposes the WPF/Silverlight XAML UI model to
developers.
- The APIs are all designed to be asynchronous.
- It is a sandboxed API, designed for creating
self-contained, AppStore-ready applications. You
wont get everything you want to create for example
Backup Software or Hard Disk Partitioning software.
- The API definitions is exposed in the ECMA 335
metadata format (the same one that .NET uses, you can
find those as ".winmd" files).
WinRT wraps both the new UI system as well as old Win32
APIs and it happens that this implementation is based on top
of COM.
WinRT Projections
What we call "bindings" Microsoft now calls "projections".
Projections are the process of exposing APIs to three
environments: Native (C and C++), HTML/Javascript and .NET.
If you author a component in C++ or a .NET language, its
API will be stored in a WinMD file and you will be able to
consume it from all three environments (Native, JavaScript and
.NET).
Even in C++ you are not exposed to COM. The use of COM is
hidden behind the C++ projection tools. You use what looks
and feels like a C++ object oriented API.
To support the various constructs of WinRT, the underlying
platform defines a basic set of types and their mappings to
various environment. In particular, collection objects in
WinRT are mapped to constructs that are native to each
environment.
Asynchronous APIs
Microsoft feels that when a developer is given the choice
of a synchronous and an asynchronous API, developers will
choose the simplicity of a synchronous API. The result
usually works fine on the developer system, but is terrible
when used in the wild.
With WinRT, Microsoft has followed a simple rule: if an API
is expected to take more than 50 milliseconds to run, the API
is asynchronous.
The idea of course is to ensure that every Metro
application is designed to always respond to user input and
to not hang, block or provide a poor user experience.
Async programming has historically been a cumbersome process as
callbacks and state must be cascaded over dozens of places and
error handling (usually poor error handling) is sprinkled
across multiple layers of code.
To simplify this process, C# and VB have been extended to
support the F#-inspired await/async pattern, turning async
programming into a joy. C++ got a setup that is as good as
you can get with C++ lambdas and Javascript uses promises and
"then ()".
Is it .NET or Not?
Some developers are confused as to whether .NET is there or
not in the first place, as not all of the .NET APIs are
present (File I/O, Sockets), many were moved and others were
introduced to integrate with WinRT.
When you use C# and VB, you are using the full .NET
framework. But they have chosen to expose a smaller subset
of the API to developers to push the new vision for Windows 8.
And this new vision includes safety/sandboxed systems and
asynchronous programming. This is why you do not get direct
file system access or socket access and why synchronous APIs
that you were used to consuming are not exposed.
Now, you notice that I said "exposed" and not "gone".
What they did was that they only exposed to the compiler a
set of APIs when you target the Metro profile. So your
application will not accidentally call File.Create for
example. At runtime though, the CLR will load the full class
library, the very one that contains File.Create, so
internally, the CLR could call something like File.Create, it
is just you that will have no access to it.
This split is similar to what has been done in the past
with Silverlight, where not every API was exposed, and where
mscorlib was given rights that your application did not have
to ensure the system safety.
You might be thinking that you can use some trick
(referencing the GAC library instead of the compiler reference
or using reflection to get to private APIs, or P/Invoking into
Win32). But all of those uses will be caught by AppStore
review application and you wont be able to publish your app
through Microsoft's store.
You can still do whatever ugly hack you please on your
system. It just wont be possible to publish that through the
AppStore.
Finally, the .NET team has taken this opportunity to do
some spring cleaning. mscorlib.dll and System.dll have been
split in various libraries and they have moved some types
around.
Creating WinRT Components
Microsoft demoed creating new WinRT components on both C++
and .NET.
In the .NET case, creating a WinRT component has been
drastically simplified. The following is the full source
code for a component that adds 2:
public sealed class AddTwo {
public int Add (int a, int b)
{
return a + b;
}
public async IAsyncOperation SubAsync (int a, int b)
{
return a - await (CountEveryBitByHand (b));
}
}
You will notice that there are no COM declarations of any
kind. The only restriction is that your class must be sealed
(unless you are creating a XAML UI component, in that case the
restriction is lifted).
There are also some limitations, you can not have private
fields on structures, and there is not Task<T> for
asynchronous APIs, instead you use the IAsyncOperation
interface.
Update to clarify: the no private fields rule is only limited to
structs exposed to WinRT, and it does not apply to classes.
UI Programming
When it comes to your UI selection, you can either use HTML
with CSS to style your app or you can use XAML UI.
To make it easy for HTML apps to adhere to the Metro UI
style and interaction model, Microsoft distributes Javascript
and CSS files that you can consume from your project. Notice
that this wont work on the public web. As soon as you use
any WinRT APIs, your application is a Windows app, and wont
run in a standalone web browser.
.NET and C++ developers get to use XAML instead.
There is clearly a gap to be filled in the story. It
should be possible to use Microsoft's Razor formatting engine
to style applications using HTML/CSS while using C#.
Specially since they have shown the CLR running on their
HTML/JS Metro engine.
Right now HTML and CSS is limited to the Javascript use.
In Short
Microsoft has created a cool new UI library called WinRT
and they have made it easy to consume from .NET, Javascript
and C++ and if you adhere by their guidelines, they will
publish the app on their appstore.
Xamarin at BUILD
If you are at build, come join us tonight at 6:30 at the Sheraton
Park hotel, just after Meet the Experts. Come talk about
Mono, Xamarin, MonoTouch, MonoDroid and MonoMac and discuss
the finer points of this blog over an open bar.
Comments
There is a long list of comments in the moderation queue
that are not directly related to WinRT, or bigger questions
that are not directly related to WinRT, .NET and this post's
topic, so I wont be approving those comments to keep things on
focus. There are better forums to have discussions on Metro.