Yeah, you read that title right. This post is going to show you how to write platform specific code using PCLs. Now, you may be thinking that I will show you some trick with an abstract base class or possibly an interface that’s gets created in the PCL, and then the platform implements the necessary code. Well, I hate to burst your bubble, but I’m not using abstract classes or interfaces. Ahhh.. okay Brian, I know what you mean. You’re talking about shared projects. Nope! Wrong again.
In this post, we will implement platform specific functionality using a PCL, and then file linking to a file that exists in the same PCL which uses pre-compiler directives. Wait… what? Let me just show you.
So I had an interesting requirement today. I have a ton of core code in a PCL that various different platforms have to reference. One of the classes had a single method that required platform specific functionality. Now, it would really suck to have to pull this one class out of the PCL and then duplicate 99% of the code on the other platforms just to have one method implementation be different. I had to keep the class name the same across all platforms and located in the same assembly. Well, this make things very difficult. So I started playing around and made an awesome discovery.
You can have a project reference a PCL, and also have that same project link to an existing file in that same PCL that has pre-compiler directives.
Let’s take a look at a very simple example. I have created a PCL called PCLFileLinking which contains a single class called Executer.
As you can see this class has one method on it called Execute, which simply writes a message to the output window. So let’s go ahead and create a few applications that target different platforms and add a reference to this PCL.
I have added a Console application, Silverlight applications, and a WPF application. Each of these projects have a reference to the PCLFileLinking project.
Let’s take a look at how each platform invokes this code.
So no matter which application we run, the message in the output window will be the same.
Well, now let’s say that I wanted the WPF application and the Silverlight application to output a different message. Since we are dealing with a PCL, we are kind of stuck. I can’t throw platform specific code into a PCL. The other way I know to get around this issue is to used linked files with pre-compiler directives, but that would mean that I wouldn’t use a PCL, but rather a different assembly or just linking files directly from the different platform applications. This does not always align the the architecture or structure of my projects and APIs.
Wait…! I know I can add pre-compiler directives to a class in a PCL. So, why can’t I just link to a file that has pre-compiler directives that is defined in the PCL I just referenced? Is that possible? Will I get a compiler error? Well, let’s find out. Let’s modify our Executer class that is defined in our PCL and add some pre-compiler directives.
Of course we have to make sure we edit the “Build” properties of the other platform projects to define these directives we are expecting. Now let’s link to this file as an existing item to each platform we need a different message for.
Now our solution looks like this:
Notice how we only linked to the file in the WPF and Silverlight applications. Now let’s run each platform and check what message is sent to the output windw.
Now everything works as I would expect. The Console application takes the default message, but the Silverlight and WPF applications get the platform specific implementation of the message.
BAM! That’s what I’m talking about!
I had no idea this was possible, and never even thought to try it until I got desperate. I honestly don’t know why or how this works, so if you happen to know, please share.
Check out sample app that demonstrates how it works.