2

I'm working on a Xamarin.Forms solution that uses a PCL library to share code between my Android and iOS projects. This has worked out great for the most part since most UI and logic code can be kept in one place. Of course, there are some platform-specific classes that I created and linked to the PCL using DependencyService, and that's fine for most classes since code is significantly different between platforms (UI layout/appearance, for example).

However, there is one subset of classes that makes use of various namespaces that are unavailable for PCL projects (notably the System.Data namespace). To get around this restriction, I had to write a DependencyService for each of these classes. My concern is that the code between Android and iOS is exactly the same, minus one or two lines. The code is quite complex and I don't want to have to remember to update it twice when the need arises.

Is there a way I can reduce the amount of code duplicated between these two projects, considering that I cannot place the code into a PCL due to necessary namespaces which are unavailable?

Mage Xy
  • 1,803
  • 30
  • 36
  • 1
    I use the `bait and switch` method (http://log.paulbetts.org/the-bait-and-switch-pcl-trick/) BUT use the same code files in the platform-specific assemblies by creating two platform-specific projects, including/linking those code files in each project via a shared-project and then use platform compiler directives for the few lines of code that change between platforms... So by mixing PCL-style code with platform directives you can skip the dup'd code PCL *requires*... – SushiHangover Feb 24 '16 at 22:05
  • 1
    (cont'd)... If you have really large interface definitions or rapidly changing ones, to save time updating the PCL dummy signatures, I use T4 templates to define and generate the interface and platform-specific partial classes... – SushiHangover Feb 24 '16 at 22:06
  • @SushiHangover nice trick. Will be sticking that one up the sleeve :) – matthewrdev Feb 24 '16 at 23:06
  • 1
    @Mage Xy, an effective way to manage those large codebases with only a few lines difference is to put the offending code into a shared-project and if-def that code. #ifdef's arent the neatest way but if its only 1 or two lines accross the whole code body the cost is fairly low. – matthewrdev Feb 24 '16 at 23:08

2 Answers2

1

I would recommend inserting a Shared Project into your architecture. I would continue to use Platform Classes that are abstracted by Interfaces for code that needs to be platform dependent and/or use Platform APIs. However, if you have code that can be shared between those Platform Classes, you can put that code in a Shared Project and have the Platform Classes reference it.

I have used this pattern before for SQlite Access. I had a need for low level ADO.net support, which means manually mapping data out of SqliteDataReader. The logic for this is common between platforms but can't go in PCL. So I have a SharedProject for Data Mapping, and my Platform Database implementations reference that project.

See below for an example class diagram.

enter image description here

Jared
  • 702
  • 1
  • 5
  • 12
0

I was able to eliminate all duplicated code using a shared project (as @matthewrdev suggested). The process was a little more complicated than I expected, though, so I'll add a guide on what I did.

  1. Create a new Xamarin.Forms shared project. (Unfortunately, I only had the option of creating a "blank app (shared)" project, which came with pre-generated Android and iOS projects. I deleted those since I already had the necessary platform projects.)

  2. Add all duplicated code to the shared project. You may need to update namespaces. For any code that you need to run specific to platform, you'll have to use #if __ANDROID__ or #if __IOS__ preprocessor directives.

  3. Add a reference to the shared project in your platform projects (in my case, Android and iOS). In VS2013, this was a little complicated since you are (apparently) unable to add references to shared projects. You either have to modify the .csproj file manually (See this answer for details) or you can use the Shared Project Reference Manager extension for VS2013.

  4. Make sure to add the __ANDROID__ and __IOS__ conditional compilation symbols to your platform projects. To do this, you need to open the project's properties, go to the "Build" tab, and add the symbol where it says "conditional compilation symbols".

These instructions are for Visual Studio 2013, but the steps are similar for Xamarin Studio and probably VS2015 as well.

Community
  • 1
  • 1
Mage Xy
  • 1,803
  • 30
  • 36