Cross-Platform Portable Class Libraries with .NET are Happening
Portable Class Libraries are the Happy Little Feature that Could. They've been chugging along, doing their thing, and it's getting to the point where they are going to pop. That's pop in a good way.
If you're not writing .NET apps for more than one target, then you likely haven't bumped into them. However for those people who are writing .NET and want it to run on everything from Watches to Phones to Tablets to Xboxen to Desktops to the Cloud, they are enjoying what PCLs can offer.
There's still a few technical and legal challenges but I'm confident they'll be dealt with and we'll be able to create great binary libraries that can be used everywhere.
There's been a bunch of recent activity in the .NET community around Portable Class Libraries and cross platform .NET. Overall, Portable Class Libraries are starting to see wider adoption, more open source libraries are being released with portable support, and the MVVM pattern is proving to be a great way to maximize code sharing in cross platform apps.
Portable Library Releases
First of all, there have been a bunch of new libraries released as PCLs recently. Three of them are from GitHub's own Paul Betts:
- Reactive UI – Reactive UI is an MVVM framework built on top of the Reactive Extensions. Version 5.0 was released last week, which is "totally Portable-Friendly", and supports the following platforms:
- .NET 4.5 (WPF)
- Windows Phone 8
- Windows Store Apps (WinRT)
- Akavache - An asynchronous, persistent key-value store. Version 3.0, which includes PCL support, was also released last week, and now "nearly all of your serialization and network access layer can be cross-platform." Akavache supports the same set of platforms as Reactive UI. This is a really amazing piece of software that deserves its own blog post. I'll do one soon.
- Splat – "A library to make things cross-platform that should be." It has cross platform APIs for images and colors, with platform-specific extension methods to go back and forth between the platform-specific native types. This looks like an elegant solution to the problem you run into if you want a portable ViewModel but you want to expose an image in it.
Next, Scott LoveGrove confessed:
I might be getting a little obsessed with PCLs at the moment. #IHaveAProblem (link).
Scott has released four portable libraries that help access web services:
- Scoreoid Portable - A Portable Class Library that gives developers access to the Scoreoid scoring system. The library provides a friendly .NET wrapper for the Scoreoid REST APIs, and uses our portable HttpClient NuGet package.
- FanArt Portable - A Portable Class Library that gives developers access to the fanart.tv film, TV, and music image resources. It also uses portable HttpClient.
- Cineworld Portable - A Portable Class Library that gives developers access to the Cineworld film and cinema listings for the UK and Ireland. It also uses portable HttpClient.
- LiveSDKHelper - A helper library to more easily use the Microsoft Live SDK. Contains strong types which the responses from the Live SDK can be deserialized into.
Another new portable library release is Budgie, a library for accessing Twitter. The .NET and Azure Teams have also released a PILE of Portable Libraries.
- HttpClient - Simplified API for talking to HTTP services, announced here.
- Microsoft.Bcl.Compression - GZIP, DEFLATE & ZIP compression works great with Http.
- Microsoft.Bcl.Async - Await/Async for down-level platforms is ready to go
- Plus, the BCL Portability Pack (adds Task, IProgress<T>, Tuple & CallerXXXAttributes to down-level platforms)
- MEF 2 in Microsoft.Composition
- TPL Dataflow (Actor/Agent-based API for coordinating async pipelines) on NuGet as Microsoft.Tpl.Dataflow, announcement here.
- Immutable Collections in Microsoft.Bcl.Immutable, announcement here
- Azure Mobile Services has a Portable Library
- Rx Extensions
Not to mention all these excellent Portable Libraries that you should be familiar with as well.
and of course, my favorite, the HttpClient, making HTTP calls easier, since, well, since a few months ago.
public static async Task<HttpResponseMessage> GetTheGoodStuff()
var httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://hanselman.com/blog/");
var response = await httpClient.SendAsync(request);
One BUILD attendee took issue with the fact that speakers were telling people that you can't use platform specific functionality from a Portable Class Library, and wrote a blog post about how you can do this with abstraction and (preferably) dependency injection.
On at least 2 occasions recently, I have heard speakers tell their audience that you cannot reference a target-specific .NET library (such as a .NET Framework 4.5 library) from a Portable Class Library. While this is technically true, it doesn't tell nearly the whole story. Even though we can't reference target-specific libraries, we can still USE these libraries. We can call their methods and access their properties under the right circumstances. We can gain access to these libraries via an abstraction. My preferred method of doing this is...Dependency Injection.
Cross Platform .NET Coolness
There's lots of great examples of code reuse, like the podcast I did with the folks who wrote "Draw a Stickman EPIC." This app has 95%+ code reuse, all written in C# and is available in every App Store there is. Here's a few others.
Also, be sure to check out my talk from the Xamarin Evolve Conference - How C# Saved My Marriage. I talk about Portable Libraries in this talk. We'll hear more about Portable Libraries at the MonkeySpace Conference in Chicago in July of 2013.
The British and Irish Lions app is a cross platform app targeting Windows Store, Windows Phone, iOS and Android. It uses Portable Class Libraries to share common code across platforms, Azure to host the services it uses, and the MvvmCross MVVM framework which I'm a huge fan of. The UK MSDN blog posted a case study of the development of the app, and there is also a prettier case study (with screenshots, infographics, etc) and a blog post by the developers. In reference to Xamarin, MvvmCross, and Portable Class libraries, they state "Given the very short time-scales for the Lions apps (less than three months from the first line of code to our first release), we simply could not have delivered a rich native experience across all platforms without the common core."
Another cross platform app that uses MvvmCross is Aviva Drive. This is an insurance company app that you can use to track your driving habits and hopefully get a discount on your insurance. The app was featured in the Tech Ed Europe day 1 keynote (about 28:40 in), focusing on how it used Azure.
On the game side of things, Taptitude is a successful Windows Phone 7 game (or rather, a collection of minigames) which was ported to Windows Phone 8, Windows Store, iOS, and Android with the help of MonoGame and Xamarin. The team reports that they have more than 99% shared code between all the platforms, which is especially important to them because they ship updates to the game about every week.
Xamarin has released an amazing .NET Mobility Scanner which analyzes code and tells you how "portable" it is and how compatible it will be with Xamarin.Android, Xamarin.iOS, Windows Phone, and Windows Store. It lists all the APIs your code uses that aren't available on all the platforms, and an overall percentage of how portable your code is. It's a very slick implementation and similar to what we've wanted to have for Portable Class Libraries. Here's a sample report for the SignalR client library. The best part is that it does all this analysis without sending your code or binaries to Xamarin. It all happens in the browser. I love Xamarin.
Phil Haack (former PM for ASP.NET MVC and now working at GitHub) wrote a blog post titled Platform Limitations Harm .NET. He argues that the Windows platform limitations should be removed from the EULAs for BCL NuGet packages.
I personally agree. Being able to reuse existing code, make portable libraries, and write apps that run in 64k or 64gigs is what makes .NET an interesting platform.