Targeting Multiple Platforms with Portable Code: Overview

As programming with .NET has become prevalent on all Microsoft platforms, targeting multiple platforms at once becomes a critical desire amongst developers. In fact, we see the future of library development moving to supporting an intersection of platforms rather than targeting just one version of the .NET Framework at a time. Mircea Trofin, a program manager from the .NET Core Framework team, wrote the following article to introduce how to do this. –Brandon

In this post, we will look at how you can use Visual Studio to write portable class library assemblies that can run on multiple Microsoft platforms. You can create a portable class library that will run on Windows 8, Windows Phone, and Xbox 360 devices. This post provides an overview of portable class libraries, and will be followed by more in-depth posts on portable code.

The need for portable .NET Framework code

.NET developers have seen a diversification of computing platforms over the last few years – PCs, RIAs, phones, cloud, Xbox, and tablets. It often makes sense to target more than one of these platforms from your app. For example, most client apps and games that are built today call into a server component to retrieve and save data (for example, a set of high scores, a list of friends, a grocery list, or a new expense report). .NET developers often create rich object models that describe that data, and expect to code to that object model on both the client and the server. Wouldn’t it be even better if you could write, compile, and test that common code just once? That’s exactly what portable class libraries enable you to do.

Many of you have asked for the option to reuse assemblies (binaries), not just source code, across projects. Sharing code across projects creates more commonality across those projects, which makes you and your team more efficient. I would guess, however, that many of you share code today by either creating copies of common code for each project, with slight modifications, or maintain a common copy that contains a significant number of conditional compilation directives. These approaches to source code reuse are relatively easy to employ initially, especially in small code bases. As your product codebase grows, you may find that these source-sharing strategies start to scale poorly. You’ll start to wonder what you need to do to share binaries instead. The APIs across the .NET Framework platforms are generally the same, so binary reuse should just work, and that’s what many of you expect.

Portable class libraries enable you to create and compile code that can run on multiple .NET Framework platforms. You can build a library that is usable across all your projects. Whatever that library does, it will do that same thing in all the apps or websites/services that you build. You avoid having multiple copies of the code or managing a set of conditional compiler directives in a common copy. For app developers who have a few common dependent libraries across a suite of apps, this feature is a pretty significant win. It is also a huge step forward for library developers who make their assemblies available to a large audience of developers who build apps for a variety of Microsoft platforms. We’ve seen library developers creating several variants of their work, one for each .NET Framework platform. Portable class libraries either remove that need completely or scope the degree of differences that needs to be supported to something smaller and more manageable.

We have added several new features to the portable code story over the last few years. It started with portability between the .NET Framework 4 and Silverlight 4. More recently, we released the Portable Library Tools for Visual Studio 2010, which added support for Metro style apps, Windows Phone, and Silverlight. In Visual Studio Professional 2012 RC, you’ll find the Portable Class Library project type, which provides fully integrated support for creating portable class libraries that you can use in .NET Framework, Silverlight, Windows Phone, and Metro style apps. You can think of the Portable Class Library project type as a set of Visual Studio and CLR features that enable binary reuse of .NET Framework code.

Portable Class Libraries example

Before we dive into the details, as part of the Visual Studio Toolbox Series, Daniel Plaisted from the CLR Core Framework Test Team shows how you can make effective use of portable class libraries in Visual Studio.

Your browser doesn’t support HTML5 video. Visit Channel 9 to see the video.

See the resources section at the end of this post for additional videos and links.

Defining which APIs are portable

Operating system platforms and devices are different in important ways. For example, phones have accelerometers, while desktop PCs do not; desktop PCs have a rich file system that you can access, while Metro style apps do not. In addition, the .NET Framework supports a variety of GUI platforms that have different requirements, so portable GUI code isn’t possible. As a result, we defined a subset of the .NET Framework that can be portable across all the platforms, and can be used by developers to accomplish common scenarios.

Supported scenarios

We used the following main scenarios to define the scope and direction of portable class libraries:

Call BCL APIs

Use the latest language features, such as dynamic programming, async and LINQ

Read and write XML

Call HTTP URIs, specifically for REST-style end-points

Call WCF services

Build Model-View-View Model (MVVM) patterns

Supported platforms

It’s easy to support the scenarios listed above for one or two .NET Framework platforms, but we needed to reach farther and support a broader set of platforms. In Visual Studio Professional 2012 RC, the Portable Class Library project supports the following .NET Framework platforms:

Supported features and APIs

Given the number of scenarios and platforms we wanted to support, we set out on two parallel efforts. We determined the intersection of APIs between the platforms and also wrote sample code for the scenarios. We found that many APIs were already common across platforms. However, certain APIs were missing from some of the platforms, which blocked a scenario. For example, we found that we were missing important types to enable building MVVM view models in portable code. Over time, and in alignment with certain .NET Framework releases, we were able to get the remainder of APIs into more platforms, so we could enable all the scenarios listed above for portable class libraries.

We decided that supporting a single set of features across all the platforms would be too restrictive and would also mean that developers who were targeting only two or three platforms wouldn’t be able to take advantage of the larger commonality between those platforms. Instead of defining a single feature set, we separated the portable platform into a set of features. In Visual Studio, you select the set of platforms that you want to support with your portable class library, which then determines the set of features and APIs you can use. We find that most developers have a business need to support a set of platforms, which is why we start from platforms. For example, using the chart below from the BCL Team blog, if you want to support the .NET Framework 4.5, Metro style apps, and Windows Phone, you can use all the APIs in Core BCL, Network Class Library (NCL), serialization, Windows Communication Foundation (WCF), MVVM, and LINQ to XML. If you additionally need to support the .NET Framework 4, you cannot use MVVM and LINQ to XML. As stated earlier, we’ve been adding features that are good candidates for portable code to more platforms, and this is why you see some of the portable features available only in the .NET Framework 4.5 and not in version 4.

How to create a Portable Class Library project in Visual Studio Professional 2012 RC

When you click OK, you are prompted to choose the platforms this library should target (meaning, which platforms will you want to reuse the binaries):

You can also access this dialog box by right-clicking the project you created, and choosing Properties. Notice the Change… button:

In the example above, the library can be reused from projects that target the .NET Framework 4.5, Silverlight 4 or 5, and .NET for Metro style apps, but not Windows Phone, Xbox, or .NET 4.

When you write code for this portable class library, you’ll have access to APIs that are available on all the platforms that you’re targeting. For example, since the library above targets Metro style apps, you won’t be able to use System.Console, since that API isn’t available for Metro style apps.

Furthermore, a portable class library can only reference other portable class libraries that support the same targets or a broader set of targets. For example, you can reference another portable class library which, in addition to your targeted platforms, also targets Windows Phone 7. You cannot add reference to a portable class library that targets just the .NET Framework 4.5 and Metro style apps, because it may try to use APIs that aren’t available in Silverlight 4 or 5, which is one of your targets. By extension of this argument, you cannot reuse target-specific libraries from a portable class library.

This concludes the first part of the series. Stay tuned for a discussion of best practices when using portable class libraries, and please do send us your questions and feedback!

I wrote a hands-on lab. You can follow the steps to develop a simple quiz game for Metro style apps, WPF, and Silverlight, and unit-test the core logic. It is intended to be completed in very little time (10-15 minutes, assuming you copy the code).

David Kean is the developer responsible for the Portable Library Project, and he has an article in the MSDN magazine, where he develops a full-fledged “continuous client”.

Bill Kratochvil’s has a great primer article in the MSDN magazine, where he describes a portable password manager.

Jeremy Likness wrote a blog post touching on the main compile and runtime mechanics of portability.

Finally, David Kean and I go deeper into the details of the implementation and future of PLIB in this Channel 9 video.

The Portable Library Tools for Visual Studio 2010 are available on MSDN. We appreciate the feedback we received from those of you who experimented with it, and we hope you’ll see how your feedback influenced our work in Visual Studio 2012.

@Daniel – you should already be able to use async/await in a portable library in VS 2012 RC, as long as your portable library targets only platforms that support async. For example, you cannot currently use async in a portable library targeting Mango or .NET 4.0.

@Björn – as of RC, you shouldn't need to add references to System.Runtime, however, maybe you're hitting a different issue. Could you provide a small repro? Thanks!

Our portable libraries must be runnable on Silverlight 5 after your response I have verified that you can use async but ONLY if you target .net 4.5 and metro which doesnt help us at all.

Since Silverlight 5 should have all the requried infrastructure to support async/await and the the guys involved in asyncbridge got it to work I expect you to be able to get it working for 2012 RTM. If you run into any problems you should be ablo to contact them and if there are some types missing that prevent you from a "clean and elegant" implementation I expect you to be able to push them into a minor silverlight update (since 5.1 was relesed recently you could call it 5.2 or a GDR).

@dsplaisted, I have so far only used asyncbridge for a small test project in order to verify if it worked or not and it seemed to work fine. (I actually downloaded the version that did not have portable librar support and compiled it for portable libraries and it seemed to work so I sent the patch which got applied really fast 🙂 ). While it seems to work fine it would be great if the support was built in from the start and it would at least feel better if MS themselves supported it so that they permanently don't break it with some update.

Right now we are not using it in any product, but that is mostly because we are waiting for 2012 RTM as the RC (and betas) have screws up vs2010 somewhat (ex SSDT, sn.exe not working etc) so we wait and hope that by the time of RTM all should be fairly straightforward to move to 2012.

@Daniel_Svensson I think it's important to distinguish the difference between platforms and libraries in your question. Async is a new feature of a few platforms (.NET 4.5, .NET in Metro, etc.) and naturally it's not a feature of older platforms (.NET 4, Windows Phone 7.5, Silverlight 5, etc.)

The "portable class library" tools in Visual Studio 2012 allow you to build a library that targets the intersection of several platforms. It can't add features to platforms that don't have them. In order to support features that the platform doesn't support, you need to include additional libraries such as AsyncBridge. This is typical for bringing platform features down-level.

> Async is a new feature of a few platforms (.NET 4.5, .NET in Metro, etc.) and naturally it's not a feature of older >> platforms (.NET 4, Windows Phone 7.5, Silverlight 5, etc.)

Actually it is only partially a new "feature", it is based on the TPL which is present in .NET 4.0 and Silvelright 5, with just some helper classes in order to help the compiler to translate the async/await keywords into code.

Yes have been some tweaking to it in order to improve performance both for Tasks as wall as the generated async/await code, but the async/await part is in principle just syntatic sugar over existing functionallity and that is way you can download Async Targeting Pack for Visual Studio 2012 (http://www.microsoft.com/…/details.aspx) .

If you compare the difference between the .NET 4.5 async/await implementation with the .NET 4/Silverlight 5 implementation (download.microsoft.com/…/AsyncTargetingPack-InstallationAndReleaseNotes.html) you will see that there are only a small set of differences which you would not be able to solve easily (ex how the executioncontext is handled, which is all about performance and should not have any). Since the Async Targeting Pack is very close to provide a subset of the .NET 4.5 implementation (e.g OperationCanceledException is missing a CancellationToken, and some functions Reside in TaskEx instead of Task) these small changes should be quite easy for you since you are already handle similar problems (missing properties etc) for other parts of the portable libraies.

I am not proposing that you should implement all async API's (which btw would be great), but only that you should provide an implementation which allows portable library code targeting these platforms (maybe by mapping/redirecting the AsyncTaskMethdoBuilder and AsyncVoidMethod builder and the related api to the specifc platform implementation) to use the async/await keywords.

> The "portable class library" tools in Visual Studio 2012 allow you to build a library that targets the intersection of >> several platforms. It can't add features to platforms that don't have them. In order to support features that the >> platform doesn't support, you need to include additional libraries such as AsyncBridge. This is typical for

> bringing platform features down-level.

Just to be clear with the details: asyncbridge does provide the helper classes used for compiling the async/await keywords everything is is supported by the Silverlight platform. It does aslo provide the static TaskEx class which is very useful, but not required in this context.

All I am asking is that since I am able to use the async/await keywords in Silverlight 5 (and .Net 4) using code wich works the same code in .Net 4.5, using nothing but the tooling supplied by you at microsoft, is that I should be able to use that same code in a portable library targeting Silverlight 5 and .Net 4.5.