3-Screen Coding Is Here: Portable Library Tools allow you to target multiple .NET platforms with one binary!

Earlier this week, we released the Portable Library Tools CTP.  You’ll need to install the VS 2010 SP1 Beta first, then it’s a quick install on top of that.

What is it?

Back at PDC in October, I did a PDC talk called 3-Screen Coding: Sharing Code Between Windows Phone, Silverlight, and .NET.  If you want to spend some time to get the full scoop on what the Portable Library Tools are all about, you watch it online by clicking here.

But if you don’t have time for that, the basic idea is as follows:

A Portable Library is a DLL that will run compatibly across a set of .NET platforms.  The set of platforms currently supported for this CTP are .NET 4, Windows Phone 7, Silverlight 4, and XNA Framework 4.0 for XBox 360. 

The Portable Library Tools CTP introduces a new project type called the Portable Class Library, which does two things:

  1. Allows you to pick which of the supported platforms you’d wish to target, and
  2. Gives you a “view” (Intellisense, Object Browser, Compiler, etc.) of the APIs that are command and compatible among those platforms

So essentially what this does is guide you in building code that you can trust will behave the same way on a set of platforms.  And, naturally, if you choose all the platforms, you get a smaller “view” of the world than if you choose a set of similar platforms.  This is because, as soon as one platform doesn’t have a given API, it can’t be in the widest set.

You can build portable libraries with VB or C#.  The project type is currently under the “Windows” node in the Add New Project dialog.  For more details, check out Justin’s post on the CLR team blog.

Why is a given API in (or not in) the subset?

When you start building a portable library, you’ll notice that the list of APIs available is smaller than you’re used to, but we think it’s still big enough to get things done.

How did we decide what to put in there and what not to?

Well, the process was pretty straight forward.  First we thought about what would be necessary to build reasonably sophisticated code that one would want to share among different platforms – the minimum useful subset.  We thought it was something like core BCL, plus basic networking, plus basic XML handling.  As we went through scenarios and writing test projects, we verified that that was the minimum set of things you needed to write useful code, at least for the scenarios we tried.

So we then took and converted that into the set of assemblies that contain such functionality:

  • mscorlib
  • system
  • system.core
  • system.net
  • system.xml

We mapped out all of their types, properties, methods, and events for all of the platforms, then took the intersection of that list.  This gave us the list of API signatures that were present in on all platforms.  We went through this list and discovered some things that should have been on a given platform but weren’t, and we filed work items to get those added.

Second, we walked through that intersection and tried to remove obsolete and duplicate ways of doing things.  For example, we did not include the old type-unsafe collection types, such as ArrayList.  We removed many of the formatting methods that did not take an IFormatProvider parameter, because supplying that has been a clear best practice.  And so on.

As this is a CTP, this is an ongoing process and open to feedback from you.  We’ll be repeating the process with some of the platform subsets, so you’ll get a larger set of APIs if you only want to target Silverlight 4 and Windows Phone 7, for example. 

So if you find an API that you think should be in the subset, ensure that it’s actually available on all of the platforms (it has to be the exact same signature), and then see the above caveats.  I’m sure we missed some things, so let us know in the comments if there’s something you really think should be there and we’ll look at it!

As it currently is, here’s what’s where:

Feature

Assemblies

.NET Framework 4

Silverlight 4

Windows Phone 7

Xbox 360

Core BCL

mscorlib.dll

System.dll

System.Core.dll

X

X

X

X

Core XML

System.Xml.dll

X

X

X

X

Core HTTP

System.Net.dll

X

X

X

-

WCF Client

System.ServiceModel.dll

X

X

X

-

XML Serialization

System.Xml.Serialization.dll

X

X

X

-

MEF

System.ComponentModel.Composition.dll

X

X

-

-

Note the inclusion of an assembly in this list does not mean all of it’s functionality is supported, only the functionality that is common between the platforms that it exists on.

How to use the Portable Library Tools to build an application

If you are careful in how you design your application, you’ll find that you can build a large part of it as a portable library.  The basic pattern is to put all of the code that you want to be portable into the portable library, and then have all the code that references a specific platform into a platform project.

So you could imagine your solution looks like the following:

  • image

Where you have one portable library that defines the service access, business logic, and view models for both a Silverlight 4 and a Window Phone 7 application.

What about UI?

When I first started working on the Window Phone 7 project in July of 2009, there was quite a bit of talk about what the right application model was between Silverlight and the phone.  Should I just be able to run Silverlight applications straight away on the phone?  Should all the XAML be portable?  Should VS have a mode where you can select your platform and modify your project for either Silverlight or for the Phone and then somehow automatically switch between the “right” code at runtime?   Should there be some kind of a importer thing that magically reformats your Silverlight app into a phone application?   The point is, there were no shortage of creative ideas on this topic.  But most of them seemed (at best) complex or error-prone.

One of the challenges to application portability – meaning the exact same application just runs on platform A and B – is that there are often different or missing facilities.    Consider the functionality that’s in System.Windows.Browser in Silverlight, which is primarily focused on accessing the DOM of the browser that Silverlight (if in-browser) is hosted in.  This has no clear analogue on Windows Phone, where Silverlight is natively hosted as a full screen application.  So such functionality is either going to missing (meaning your app crashes at runtime) or stubbed out (meaning your app probably crashes at runtime!).  There are a wide range of these types of differences and it’s not easy to deal with them in a consistent way.  To do is a lot of extra work devoted to things that most developers won’t ever try to use in their platform-specific applications anyway. 

More importantly, is that for an app to be really useful, it needs to conform to the UI paradigms and input methods of the target platform.  Consider the DataGrid control in Silverlight, and how it is used.  This is a control that’s really designed to be used with a mouse and keyboard.  

I spent some time writing applications for Silverlight and then writing them for the phone, and as I did so it became clear that sharing UI wasn’t as great as it sounded.  In fact, with well written ViewModels, it was much, much easier to craft nice, specific XAML for each platform and then just quickly use Blend or Visual Studio to wire it up and take advantage of the powerful, flexible databinding system that the Silverlight runtime provides.  Creating the UI specifically for each platform is critical to delivering applications with a great user experience.

The Portable Library Tools CTP doesn’t yet allow you to reference System.Windows.dll, functionality, but that is planned for a future release.  This gives you access to the Silverlight UI types like Button, Grid, UIElement, and Storyboard.  So while sharing UI isn’t that useful, being able to write sharable components that reference or modify UI can be.   For example, it’s nice to be able to share things like value converters.

What’s missing?

Our goal for this CTP was to get something usable out there and see what people were able to do with it, and then let feedback drive what we focus on.  Many things we know about and are working to get them added, but there are probably some important small things that we missed.

For things that can’t be in the portable subset because they are different across each platform, there are ways of dealing with this cleanly (okay, fairly cleanly) within your application.  I’ll cover that in an upcoming post.