The Microsoft BCL team recently released the RTM version of Portable Libraries (PL). This PowerTool for Visual Studio 2010 SP1 allow you to develop managed assemblies for more than one target .NET framework. It will let you aim your code at both the full .NET Framework, Silverlight, Silverlight for Windows Phone 7 and/or Xbox 360. By using the Portable Libraries you can control which targets you are aiming for and compile a single assembly that will work on all targets you selected.
The Portable Libraries has features that are close to, yet different from another piece of functionality in Visual Studio: multitargeting. It is similar in that it will help you find the allowed subset of functionality in the .NET Framework given the combination of targets you select. It is different, because it will let you have a single project where you would normally have multiple projects for class libraries targeting .NET FX (versions 2.0 to 4.0, with full or client profile) and Silverlight. For Xbox 360 you have the Xbox 360 Game Library which comes close, but is a different thing altogether. PL projects are class libraries which can host reusable managed code over all of the previously mentioned.
You can install the tooling for PL from here. Once you have done that, a new library project is available:
A Portable Library project has its own project template. The main difference from a regular class library is in the AssemblyInfo.cs file. The contents are trimmed, because ComVisibleAttribute and GuidAttribute do not make sense for Silverlight and Xbox and are not allowed. The other difference is an extra tab on the Project Properties page. It allows you to specify the targets for your library.
In the screenshot below you can see a Class Library project converted to a Portable Library. The references to assemblies that are not part of the allowed assemblies for the targets are indicated with exclamation marks, just as when you had selected a not allowed assembly for the .NET Target Framework in a normal Class Library.
The Portable Libraries have a different build target, which further distinguishes them from regular class libraries.
The allowed set of assemblies is listed here, but to give you an idea, it is limited:
System.Windows.dll (from Silverlight)
This set is the largest possible if you are only targeting .NET Framework 4. For Silverlight and Phone 7 you cannot use MEF (System.ComponentModel.Composition), and for Xbox 360 you can only use the bold assemblies.
The use of the Portable Class Library project will pay of in finding which classes you can use and which not. If you are in doubt, you can check the MSDN documentation and make sure. Here is an example for the System.Runtime.InteropServices.StructLayoutAttribute class:
In the type’s members you can see whether a particular member is supported (when the type itself is):
The small project icon in the left column means it is supported.
An example scenario
Let’s say you have a piece of C# code that can be reused in an application or game for Windows, Phone and Xbox 360. Normally (without Portable Libraries), you would need to set up several projects:
Each of the ReusableGameCore libraries contain the same code, but have a different target. They are referenced by the corresponding game (or application) version for Windows, Phone and Xbox.
You need to do so, because the build target need to be different for the various consumers of your reusable code. For example, referencing a normal Class Library project in an XNA Game Studio 4.0 project for Xbox 360 will get you compile errors. It will complain about the “wrong” target framework being selected, even though you have changed it to .NET 4 Client Profile (or something else).
As you can see in the screenshot the code in the Silverlight and Xbox360 library projects is linked from the Windows version. You will only have one version of the code, but having three project is not ideal.
The alternative is offered by Portable Libraries. In that case the three libraries can be combined into a single one. Your solution will look like this:
The three other projects each reference the single portable class library. Quicker to set up and easier to maintain. Moreover, you can install additional frameworks, which allows you to target other or more from the same library.
Converting a Class Library to a Portable Class Library
It could very well be that you have a Visual Studio solution that holds class libraries which you would like to be Portable. One option is to create a new Portable Library project and transfer the files from the class library to the new Portable project. This should be the normal way to go. I tried whether it is possible to convert the class library project into a portable one. Turns out that it can be done. Here’s how:
- Unload the Class Library project. Right-click the project and select Unload Project from the context menu to do so.
- Edit the .csproj or .vbproj file. Pick the option from the context menu.
- Add the following fragment to the first <PropertyGroup> under the <Project> root element:
- Remove the <ProductVersion> and <SchemaVersion elements:
- Change the <Import> element just before the closing tag of the <Project> element to the .
- In C# replace
<Import Project="$(MSBuildToolsPath)Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)MicrosoftPortable$(TargetFrameworkVersion)Microsoft.Portable.CSharp.targets" />
In Visual Basic replace
<Import Project="$(MSBuildToolsPath)Microsoft.VisualBasic.targets" />
<Import Project="$(MSBuildExtensionsPath32)MicrosoftPortable$(TargetFrameworkVersion)Microsoft.Portable.VisualBasic.targets" />
// Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("1e49a9ca-89db-46d1-9704-b76e10897ffb")]
Please note that this is not an official and therefore not supported migration. No guarantees and make sure you have backups, checkins et cetera before you undertake this conversion.