Getting Xamarin.Forms apps working with .NET Standard and Roslyn

Recently, I was trying to write a Xamarin.Forms app that uses Roslyn, Microsoft’s NET languages compiler framework. But, no matter what I did, it seemed as though it wasn’t possible. But, I tried a few things, and noticed that the Roslyn library could link with Android and iOS applications. That’s when I realized it might be possible.

That said, it depends on what you will be interested in of the Roslyn API. While one can parse and compile code from the .NET Standard/PCL library, Assembly.Load is essentially unavailable. Full functionality is available in Xamarin Android version 7. If you want to run compiled code, you need to use a bait/switch layer to accomplish that, in which case, you don’t need to make your PCL into a .NET Standard library, but it’s a good idea anyways.

Also, I’ve noticed VS 2015 is quite brittle in setting up an app to use .NET Standard. The following steps show that it can be done. Note: after each step, verify with a build and run.

  1. To set up a Xamarin Forms app to use the .NET Standard, open Visual Studio 2015 and create a blank cross-platform app that uses portable class libraries. You will see a portable class library and apps for each of the platforms.
  2. In the Project Explorer, Remove the Windows, Windows Phone apps, and leave the Android and iOS apps.
  3. Set the default project to the Android project. Build and run to make sure all is OK.
  4. Update the Xamarin.Forms in the three projects, to the latest version of Xamarin.Forms (2.3.3.175). Rebuild and run to make sure it works.
  5. In the Project Explorer, right-click on the References for the Xamarin Forms app portable class library, and “Manage NuGet Packages.” Remove the Xamarin.Forms library.
  6. Right-click on the portable class library, select Properties. Click on the Target .NET Standard hyperlink, then select NET Standard 1.5. Note, if you use .NET Standard 1.6, the References suddenly drops all DLL references, so don’t use that! In VS 2017, that appears to be fixed. Once VS has made the conversion, project.json will appear. After making the conversion, the default project has been reset. Set it back to the Android project.
  7. In the file project.json, change the ‘frameworks’ section with the following code, which allows the .NET Standard library to be compatible with certain PCL libraries.
 "frameworks": {
   "netstandard1.5": {
     "imports": [
       "portable-net45+wpa81+wp8+win8"
     ]
   }
 }
  1. Go back to the NuGet package management for the Xamarin Forms app PCL, add in Xamarin.Forms (the latest version).
  2. Rebuild and test. It should all work fine. If not, there is probably something wrong with your VS. Make sure it has the latest updates.

Roslyn works with .NET Standard, but adding it blindly causes a dependency/version issue. Roslyn requires Microsoft.Composition, but the version that it requires is old and incompatible with the .NET Standard (Package Microsoft.Composition 1.0.27 is not compatible with netstandard1.4 (.NETStandard,Version=v1.4). Package Microsoft.Composition 1.0.27 supports: portable-net45+win8+wp8+wpa81 (.NETPortable,Version=v0.0,Profile=Profile259)). Instead, add Microsoft.Composition first, then Microsoft.CodeAnalysis.

  1. In the Project Explorer, right-click on the References for the portable class library, and “Manage NuGet Packages.” Add in Microsoft.Composition (1.0.30), then Microsoft.CodeAnalysis (1.3.2). Make sure to add that to the Android project as well or you get “Severity Code Description Project File Line Source Suppression State
    Error Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly ‘Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’. Perhaps it doesn’t exist in the Mono for Android profile….”

For a check, add source referencing some Roslyn classes, build and run.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace App15
{
    public class Class1
    {
        public Class1()
        { }

        public static void YoDoit()
        {
            SyntaxTree tree = CSharpSyntaxTree.ParseText(@"
            public class MyClass
            {
                public int MyMethod()
                {
                    return 1+2;
                }
            }");
        }
    }
}

This code is in Github: https://github.com/kaby76/XamForms-Roslyn-Example

Leave a comment

Your email address will not be published.