When I want to share code between projects, I usually create class libraries. Depending on the kind of projects where I want to reuse my work, I may need portable libraries (PCL) or even shared source projects. I had worked with PCL libraries before, but not with universal and shared source projects, and I think it’s important to be clear about the differences between each type, because they play very different roles.
The first thing to keep in mind is that the goal of all these project types is simple: sharing code. They all aim to let us share as much code as possible when we work with projects that will run on different runtimes. In this case, it all started simply because I wanted to share a module between a Windows 8.1 app and a WPF one, but you can find more complex scenarios that include Windows Phone or Xamarin projects.
The starting point is that there hasn’t been a single .Net framework for a while now. Before, you only had to worry about the framework version to know whether some features were available or not, because you always had the same runtime environment. Now, depending on the type of project I’m working on, I find that the same framework version gives me different capabilities depending on the platform it runs on. This means I won’t have the same capabilities available everywhere I try to reuse my class libraries.
PCL libraries
When you create a PCL library, you have to specify the .Net versions it’s meant to be used with. This choice, which you can change at any time, determines which .Net features you’ll be able to use, as well as which third-party libraries you can use.
For example: if you want to use dynamics, keep in mind that the library can be used from desktop .Net applications and Windows 8 Store apps, but it can’t be used by Windows Phone apps.
If you want detailed information about PCL libraries and the features available on each platform, the official documentation is this one. If you want to build PCL libraries compatible with Xamarin, they also provide documentation on the subject.
In this one, we used PCL libraries for Windows 8.1, Windows Phone 8.1, and .Net 4.5 for the REST service client classes, DTOs, etc. We even share some ViewModels. For example, we have an interface that defines a mechanism to persist logging and telemetry data. Since the implementations depend on each platform, the PCL library only contains the interface to implement.
Universal libraries
Among PCL libraries there are the so-called universal libraries. They showed up along with the concept of universal apps with Windows 8.1 and Windows Phone 8.1 and, in essence, they’re PCL libraries meant to be used only in Windows 8.1 modern UI and Windows Phone 8.1 apps. With the arrival of Windows 10, these libraries extend to other platforms, such as Xbox, HoloLens, and Raspberry Pi 2.
This means we can’t use these libraries in desktop or web .Net projects, for example. Personally, given their limitations, I think the name universal was badly chosen 😉
For the persistence interface mentioned in the previous example, the first two implementations I needed just wrote the data to disk to be processed later by other modules of the application. Since universal apps don’t have access to the System.IO namespace, I went with two implementations: one in a universal library, which used the StorageFile class, and another in a traditional library, which does have access to System.IO.
Shared source projects
These projects are peculiar. They aren’t even projects you can compile on their own. When you create a universal app, a shared source project gets created, although there’s an extension that lets us do it manually to use shared source projects in existing solutions and projects.
Using a shared source project is the closest thing to sharing a folder between two projects, except that the way to share it is by adding the shared source project as a reference. During compilation, the code of the shared project is included as part of the whole compilation process of the project that references it.
Going back to the previous example, for Windows 8.1 and Windows Phone 8.1 I developed an implementation that persisted to SQLite. The code to access the SQLite API is the same on both platforms, but the reference you need to add is different on Windows 8.1 and on Windows Phone 8.1, so I can’t call that code from a Universal project. Using a shared source project, I can add the right SQLite reference to each project but reuse the code that uses SQLite in both of them.
It’s important to remember that the code in shared source projects is not compiled as a separate assembly, but as part of each project that references it, as if it were the project’s own code.
In this post you can see an example of using them with Xamarin projects.