-
Notifications
You must be signed in to change notification settings - Fork 6
Overview
If you are developing a Portable Class Library, PCL, based on legacy .NET code, you are likely to encounter types, methods or properties that are available in .NET, but not in the PCL profile you are targeting.
To handle this issue, you could of course edit the legacy source code to use a PCL analog of the missing type, method or property.
However, if you have a large code base, or if the legacy code is still under development and is continuously updated, making the PCL edits could be quite burdensome.
And this is where the Shim project can help. The Shim library contains dummy or basic implementations of a fair bit of types, methods and properties that are available in .NET but not in specific PCL profiles. By referencing Shim from the Portable Class Library you are developing, there is no need to edit the original code when you are faced with for example a type that is not existing in the PCL profile. As long as this type is represented in the Shim library, you can keep your code untouched.
A very often occurring example is the presence of the SerializableAttribute
in .NET legacy code:
[Serializable]
public class SomeClass { ...}
SerializableAttribute
is not available in any PCL profile, but it is available in Shim. If you reference Shim in your PCL project, you do not have to remove the [Serializable]
decoration from your code.
In the specific case of SerializableAttribute
it is just a dummy declaration. There is no binary serialization engine implemented in Shim, so binary serialization will not work for example in Windows 8.1 or Windows Phone 8 Silverlight applications. It will, however, still work in .NET and Xamarin applications, as is further explained below.
Shim comes in many versions for different platforms or combinations thereof, to ensure that Shim is properly optimized for each platform it is currently targeting. When referencing Shim, you should select the version that best fits the platform your class library or application is targeting, otherwise Shim will work sub-optimally or not at all.
When applying Shim via NuGet, selection of the proper Shim version is done automatically by the NuGet Package Manager, so in normal cases you will not have to concern yourself with appointing the correct Shim version. It will be handled automatically by NuGet.
One crucial thing to keep in mind, though:
If you are developing an application for a specific platform, for example Xamarin Android or .NET, and this application references a Portable Class Library that consumes Shim, you need to explicitly reference the Shim version for the specific platform in your application also! If you reference Shim via NuGet, the correct platform version will be automatically picked, but you still need to enter an explicit reference.
The reason for having platform-specific versions of Shim is simple: otherwise it will not work :-)
A Shim version aimed for a Portable Class Library will contain implementations of a number of types that are not available in the specific PCL profile, but are available for example in .NET or Xamarin. If you try to reference (implicitly or explicitly) the PCL version of the Shim library in a .NET application, the .NET application will see two implementations of a type with the same name, and this will lead to a build error.
Therefore Shim comes in for example a .NET specific version. Instead of providing implementations of the various types in the PCL version of Shim, the .NET version only provides type forwarding of the same types, like this:
[assembly: TypeForwardedTo(SerializableAttribute)]
With this technique, the .NET application will only see one implementation of the SerializableAttribute
, and can thus be built without concerns about duplicate type implementations.
This technique has the added benefit that as long as you are working with the .NET application, you have access to the full implementation of SerializableAttribute
in the .NET Framework and do not have to rely on the dummy implementation from the Shim PCL version. Thus, you will be able to perform binary serialization as usual in your .NET application, even if the application references Shim.
All versions of Shim are named identically, using strong naming. It is because the libraries have the same strong name that it is possible for example in the .NET application to incorporate the .NET version of the Shim library even if the PCL library that the .NET application is incorporating references the PCL version of the Shim library. Since the strong name is the same, the .NET and PCL versions of the Shim library are interchangeable.
This is an example of the so-called "bait-and-switch" technique, which is described in fair detail in this blog post by Paul Betts. The technique has also been used in other projects, perhaps most notably the PCLStorage project.