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.
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.
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
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:
- .NET Framework 4, Update 4.0.3 for the .NET Framework 4, and .NET Framework 4.5
- .NET for Metro style apps
- Windows Phone 7.x
- Silverlight 4 and 5
- Xbox 360
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.
Table 1. Supported portable class library features and scenarios
You can learn more about the full set of APIs supported in MSDN.
How to create a Portable Class Library project in Visual Studio Professional 2012 RC
It’s very easy to create a portable class library. In Visual Studio 2012 RC, choose File, New Project, and then choose Portable Class Library:
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!
Here’s some additional links for learning more:
- The MSDN Library provides an overview and example, discussion of API differences, an example of using portable class libraries to implement the MVVM pattern, and information about managing resources in portable class library projects.
- 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.
- We are trying to bridge more gaps in portability in the PCLContrib CodePlex project.
- 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.