Banish Compiler Directives From Shared Projects!

Shared Projects definitely take their share of bashing – if you spend any time at all talking to somebody who used Shared Projects in their app – they’ll spend the entire conversation staring at the ground, eventually apologize profusely and then offer to buy you lunch – because well … PCLs! In fact, one would think that compared to PCLs, Shared Projects are inferior and if you use them, your app will be full of bugs and will never get downloaded!

Now I’m not going to spend this entire post defending Shared Projects, or giving instructions on how to use them – I already did that here and here and here. But one of the things I hear people complain about with Shared Projects more than anything else is that you need… NEED… to use compiler directives with them.

Stop the presses! You don’t need to use compiler directives! With some creative use of partial classes and what I call the poor man’s bait and switch … the only time you’ll have to see that hashtag again is when you’re tweeting how awesome this post is! (Let’s agree to use #SharedProjectsRule, shall we?)

OK – I’m fooling around and being sarcastic … but I am serious that you don’t have to use compiler directives with Shared Projects. Let me demonstrate how to with the super cool Native Control Embedding feature from Xamarin.

I’m going to take James Montemagno’s blog post introducing Native Embedding and refactor it so it doesn’t use compiler directives. You can find the finished solution on GitHub here.

(That blog post creates an UISegmentedControl in iOS and a FloatingActionButton in Droid and adds them to the same screen in a Xamarin.Forms app.)

Partial Classes

The key to all of this is partial classes. That’s right – the shining feature of C# 2 (yup, C# 2) saves the day when looking to avoid using compiler directives. As I’m sure you know already – partial classes allow the implementation of a class to be broken apart across multiple files.

That means there could be part of a class contained within the Shared Project and the other part contained within the platform project. When the app gets compiled – the two class files get combined together like they were one single file.

For the Native Embedding portion of the demo app … or for any portion that needs to access platform specific code … create a partial class and put the platform specific stuff in the portion that lives in the platform project.

So when we need to create a UISegmentedControl – it will live in a function within the partial class in the iOS project.

All of that could have been put within a compiler directive right inline of the Shared Project … but we’re staying away from those hashtags!

Then to consume it in the SharedProject – it will look like the following:

Cool … but how to guarantee both the iOS and and Droid projects implement the same functions?

The Poor Man’s Bait ‘n Switch

The Bait ‘n Switch trick was invented to provide platform specific functionality when using PCLs. The super brief, and not 100% correct summary is that Bait ‘n Switch provides an “empty” implementation of a particular function in the PCL layer but a full implementation in the platform layer. Everything is programmed against an interface – that way when you invoke a function in the shared layer, it’s really getting the platform version of it. There’s more to it – read this post – it’s cool.

In this scenario, the poor man’s version of that is done. In the Shared Project there’s an interface that defines the function GetControlForNoDirectivesPage .

Then there’s an empty partial class in the Shared Project as well that implements that interface.

It’s empty! It implements the interface! That means the other half of that partial class in the platform projects are going to have to implement it!

The key is the empty partial class in the Shared Project. Since the Shared Project doesn’t emit a DLL, it becomes a part of whatever references it. So if there’s a partial class in the Shared Project that doesn’t fully implement an interface – there’s going to have to be a full implementation of the interface in the platform project.

Poor man’s bait ‘n switch!

Shortcomings

There’s a couple of things here that I don’t love. The first is that I’m passing in the layout of where the native control will be inserted into – and in the iOS project then looking up by name a child of that layout. I don’t like that. However … since the Shared Project becomes one with the platform project … it’s not the end of the world … and there’s plenty of use cases where this wouldn’t be an issue at all.

There’s also the argument to be made – what’s worse – compiler directives or multiple files? I’d say compiler directives – at least with multiple files all the platform specific code is within the platform’s project.

Summary

Finally – with the use of partial classes and the poor man’s bait ‘n switch, you can free your Shared Projects of compiler directives once and for all! Now there’s no excuse to use a PCL as the core project of a Xamarin.Forms app ever again! (Because when would you ever share that project with another app anyway?) 🙂

Now … if you’re writing a library … PCL. All the way.

Matthew Soucoup on sabemailMatthew Soucoup on sabgithubMatthew Soucoup on sablinkedinMatthew Soucoup on sabtwitter
Matthew Soucoup
Matthew Soucoup
Matthew is a Xamarin MVP and Certified Xamarin Developer from Madison, WI. He started Code Mill Technologies and is the founder of the Madison Mobile .Net Developer's Group. 

Matt regularly speaks on .Net and Xamarin development at user groups, code camps and conferences throughout the nation, including Xamarin Evolve, That Conference, Prairie.Code(), MKEdotNET, St. Louis Days of .Net, and CodeMash.

When he's not developing cross platform apps, writing blog posts, or creating the next great talk, Matt enjoys brewing beer with jalapeños from his garden and playing 80s tunes on the piano.

1 Comment

  1. Nice post! I’ve been using partial classes like this since the first MonoTouch days and it beats the hell out of fiddling with DI containers 🙂

    I sometimes also leverage partial methods, which can help to inject some platform specific behaviour in otherwise cross platform functionality.

    Reply

Trackbacks/Pingbacks

  1. 7 Key Decisions for Any New Xamarin Project – Software Drivel - […] Before we can start coding, the second step of a new project asks us to decide how we want…
  2. Bindable Native Views in XAML – With Commands!?! | Code Mill Technologies - […] but it isn’t optimal. You have to mix code-behind with XAML … AND … either use Shared Projects or…

Submit a Comment

Your email address will not be published. Required fields are marked *

%d bloggers like this: