Sharing code across platforms

Sharing code across platforms

Rate This
  • Comments 9

At Build we announced two great ways to re-use your code: the new Universal Windows apps, and the improved portable class libraries. They both help you reuse code across platforms.

In this post, I’ll describe both options and how you can choose between them.

Overview

Why two options? The short answer is that shared projects are about sharing source code and assets, while portable class libraries are about sharing binaries:

  • Shared projects are great when your common code has a few bits of platform-specific code, since you can adapt it with #if.

  • Portable class libraries are great when your common code is platform-independent as well as for reusable libraries where the platform-specific code can be factored out.

Visual Studio 2013 Update 2 makes code sharing as simple as sharing cookies

Shared projects

Visual Studio has supported linked files for as long as I can remember. Linked files allow you have the same physical file be included into multiple projects. However, even Visual Studio 2013 only supported linking individual files, which tends to become cumbersome when multiple files and projects are being used.

Visual Studio 2013 Update 2 introduces the new feature Universal Windows apps. It’s implemented via a general mechanism called shared projects. Shared projects are linked files on steroids. Instead of linking individual files, you can place them inside a shared project. The files are then linked as single entity by adding a reference to the entire shared project.

Behind the scenes, Visual Studio still thinks of them as linked files which means that many of the improvements we made also apply to linked files. If all you need is to share a single file, for example AssemblyInfo.cs, then linked files are still an excellent tool. We’ve also removed the notorious “the file is already open” error message when you open the same file from a different project. There are also some really cool new features around how the IDE presents the shared code. Make sure to check out the post on Universal Apps.

The major benefit of shared projects is that you can easily handle cases where your code needs to call different APIs, depending on the target platform. You can do this via conditional compilation:

public class NavigationHelper
{
    public NavigationHelper()
    {
        #if WINDOWS_PHONE_APP
            Windows.Phone.UI.Input.HardwareButtons.BackPressed
                += HardwareButtons_BackPressed;
        #elif WINDOWS_APP
            // Ignore. Windows Store doesn't have support for this.
        #else
            #error Unknown platform
        #endif
    }

    // ...
}

The preprocessor symbols, such as WINDOWS_PHONE_APP, are defined by the project and are usually already provided by the template. You can find them on the Build tab in the project properties:

Note: Right now, shared projects are only supported in the context of building Universal Apps. Moving forward, this may become a general purpose feature. There is a preview of how this may look like.

Portable class libraries

One source code, one binary, multiple platforms. That’s the promise of portable class libraries. In Update 2, we’ve improved portable class libraries quite a bit:

  1. You can now consume & produce WinRT APIs
  2. You can now create & design portable XAML user controls
  3. You can now easily convert a platform-specific class library into a portable class library by adding another platform:

Portable class libraries present the developer with the intersection of APIs that can be shared across all the selected targets. This allows producing a single binary that is guaranteed to run on all of the targets. Producing a single binary gives you the following benefits:

  • You can easily redistribute the component to 3rd parties, outside your solution. This includes sharing the binary directly as well as sharing it via a package manager like NuGet. Either way, consumers just add a reference to it and are good to go. Thanks to the “C” in “CLR” it also doesn’t matter which programming language the library was written in.

  • It’s the same component, on all platforms. This makes it super easy to reason about your components. It also streamlines testing quite a bit.

Good examples of libraries that take advantage of portable class libraries are JSON.NET and immutable collections.

Choosing between shared projects and portable class libraries

The rule of thumb is:

  1. If you have to use platform-specific APIs and you only need to share within the same solution, shared projects will have the best experience.

  2. If you don’t have to use platform-specific APIs or you need to share with consumers outside of your solution, portable class libraries provide the best experience.

When you have to share your code with consumers outside your solution and you need to use platform-specific APIs, you need to make a trade-off decision. The following table gives you some orientation by highlighting the strengths and weaknesses of each approach. Of course, you can also use a combination.

  StrengthsWeaknesses
Shared Projects
  • Allows using platform-specific APIs by using #if
  • Can handle cases where the source is compatible but the binary wouldn’t be, for example, when APIs are in different namespaces
  • You have to either share the source or multiple binaries which forwards part of the complexity to the consumer
  • Requires convention and discipline to centralize handling of divergent APIs so that the code doesn't become an unmaintainable mess
Portable class libraries
  • Extremely simple deployment and sharing model
  • Scales well to larger systems which requires multiple solutions, involves 3rd parties or multiple programming languages

Summary

Code reuse is a multifaceted domain and as such there isn’t a one-size-fits-all solution. As a developer, you want to be able to select the best tool for the job. Therefore we’ve updated Visual Studio such that it provides you with multiple options in order to be even more productive.

Starting with Visual Studio 2013 Update 2, you have first class support for sharing source code as well as for sharing binaries. Shared projects provide a light-weight and flexible way to bridge platform differences. Portable class libraries are great for building cross-platform components that can be easily deployed and reused by 3rd parties.

Use the power and share with love!

Leave a Comment
  • Please add 4 and 4 and type the answer here:
  • Post
  • >"Because code re-use is a multifaceted domain which simply doesn’t have a one-size-fits-all solution"

    PCL is about binary sharing, not code sharing. I agree that PCL doesn't fit all, but linked files/shared projects do. It's the perfect code sharing solution and it never have the "least common denominator" limitation of PCL. Sharing code files isn't really an issue nor is dealing with 2+ binaries, but running into the "PCL Wall" is a major limitation, and when it happens (which it almost always does), you're back to re-architecting your projects, or you're writing a crazy set of interfaces, dependency injection and inversion of control etc etc, ruining the productivity and forcing you to share less code even though the multiple interface implementations are mostly identical anyway and if-def would have been much quicker anyway,. Just my $0.02

  • I got hopeful when I read "3.You can now easily convert a platform-specific class library into a portable class library by adding another platform:" but that does not seem to work for me or at least it did not do what I thought you meant.  It would be handy to have a way of converting a non portable class library to a portable class library without having to unload the project and hack the xml of the project file.  

    It would also be great to get a XAML pre processor but I have been asking for that since the first release of Silverlight and so I wont hold my breath.  I would live without the designer in visual studio in favour of having a XAML pre processor.  I have never used the XAML designer and probably never will.  Come to think of it an option to turn the xaml designer off entirely would also be of use to me and then hopefully I would not get a ton of Microsoft Visual Studio XAML UI Designer processes hogging 100-200MB a piece.

  • >>Moving forward, this may become a general purpose feature.

    Please make Shared Projects a general purpose feature.  We do Compact Embedded development and we have source code shared between desktop and CF.  Right now we have a customized version of the C# targets file to handle this.  The Shared Projects feature would be much better!!

  • @Morten:

    >> PCL is about binary sharing, not code sharing. I agree that PCL doesn't fit all, but linked files/shared projects do.

    It depends. The nice thing about PCLs is that you can deploy a single binary, which is often exactly what you need.

    >> It's the perfect code sharing solution and it never have the "least common denominator" limitation of PCL.

    Did you try the improved PCLs? I'm curious to what the limitations are you're still running into.

    @Martin:

    >> I got hopeful when I read "3.You can now easily convert a platform-specific class library into a portable class library by adding another platform:" but that does not seem to work for me or at least it did not do what I thought you meant

    Which class library did you try to convert? The in-place conversion is currently only supported between PCL, Windows Store and Windows Phone. Moving forward, we intend to expand it to the targets that PCLs support (of course, I can't commit at this point).

    >> XAML pre processor

    That's great feedback. I've forwarded it to the team that owns the XAML designer.

    @Keith:

    Makes complete sense. I've forwarded your feedback to the people that plan & drive the next version of the overall feature area.

  • For all of you who would like to use #if in XAML, please vote on this user voice item:

    visualstudio.uservoice.com/.../3767159-allow-conditional-compile-statements-in-xaml-marku

  • Does universal include windows 8 desktops or is it just for tablet/phone/store applications?

  • @Ralph: Universal Apps are currently only supported for Windows Store 8.1 and Windows Phone 8.1 platforms. We may change this in a future version of Visual Studio. You can get a very similar experience today by using the preview of the Shared Projects Visual Studio extensions.

  • So when will the Universal App template be available for VB.NET? I see that it is available for some of the other languages like C#, but not for VB.NET. If it's already been made for C#, can it really be that hard to make the version for VB.NET? I thought it was supposed to be available with Visual Studio 2013 Update 2, but apparently it isn't.

  • @Nathan Sokalski: First of all Universal Windows apps is a store concept that you can also leverage from VB. Lucian has written a great post on that here: blogs.msdn.com/.../vb-universal-app-part-1-getting-started.aspx.

    I can't comment on any plans for making shared projects available to VB. However, VB does support regular linked files & portable class libraries.

Page 1 of 1 (9 items)