Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MvvmCross assembly referenced from Cirrious.MvvmCross.dll could not be loaded: System

I'm trying to set up a MvvmCross application project and run unit tests against it (namely the view models in it). I'm using Xamarin Studio on OS X (v. 4.0.4, latest at the time of writing).

The MvvmCross App is set up as a portable class library. The test assembly is set up as a plain Mono/.Net assembly (not PCL) referencing the NUnit framework.

When trying to execute the tests, they fail with a System.TypeLoadException.

I have run the tests with the Mono binding log on. Here's the output:

Mono: The following assembly referenced from /Users/jr/dev/rowinginmotion-cross/RowingInMotion.Mobile.BoatApp.Tests/bin/Debug/Cirrious.MvvmCross.dll could not be loaded: Assembly: System (assemblyref_index=3) Version: 2.0.5.0 Public Key: 7cec85d7bea7798e System error: Invalid argument

Mono: Failed to load assembly Cirrious.MvvmCross[0x559960]

Mono: Could not load file or assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies.

Is this test setup not supported=

like image 421
Johannes Rudolph Avatar asked May 08 '13 13:05

Johannes Rudolph


2 Answers

This problem is linked to the fact that Xamarin and Mono don't yet properly support Portable Class Libraries - instead they compile and link against local fixed assemblies depending on what version of Mono (Xamarin.Android, Xamarin.iOS, etc) you have loaded - see http://slodge.blogspot.co.uk/2013/01/almost-portable-binaries.html for some more information.

On Windows, you would be able to get around this problem using BindingRedirect functionality, but I haven't yet found any way to get around the problem using XBuild within Xamarin's environments (e.g. see my PCL and Mac issues on http://forums.xamarin.com/discussion/3733/playing-with-pcls)

The only way I can see of currently loading this code in a full .Mac (.Net) project is to use the Xamarin recommended approach of file-linking - duplicating the project files and compiling the duplicate specifically against the appropriate target.

Hopefully this is changing soon - as the official PCL support is due in alpha in the coming days and weeks.

like image 98
Stuart Avatar answered Nov 03 '22 07:11

Stuart


In addition to @Stuart's answer (which is correct), I want to post a second workaround that I found allows me to achieve my desired scenario (PCL assembly testable on Mac OS and Windows).

This workaround relies on Xamarin Studio 4.0.5 (or later) that introduced support for wildcard includes.

Specifically, when compiling on Windows I compile the PCL and add a project reference to it from the test assembly. On Mac OS, I compile the 'PCL' (there's no true PCL support right now) too but I leave it untouched from the test assembly. Instead, I wildcard include all code from the PCL project into the test assembly so I have test+code in the test assembly on OS X.

This requires some MSBuild magic (similar trick used to switch MvvmCross references between Windows and OS X version). Include this .targets file at the top of your projects:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
    <MvvmCrossPlatform>VS2012</MvvmCrossPlatform>
    <PclSupport>true</PclSupport>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
    <MvvmCrossPlatform>XS-iOS-Mac</MvvmCrossPlatform>
    <PclSupport>false</PclSupport>
  </PropertyGroup>
</Project>

Then in your unit test .csproj:

  <ItemGroup Condition=" '$(PclSupport)' == 'false' ">
    <Compile Include="..\RowingInMotion.Mobile.Backend\**\**.cs">    
      <Link>_Inlined\%(RecursiveDir)%(FileName)%(Extension)</Link>  
    </Compile>
  </ItemGroup>

  <Choose>
    <When Condition=" '$(PclSupport)' == 'true' ">
      <ItemGroup>
        <ProjectReference Include="..\RowingInMotion.Mobile.Backend\RowingInMotion.Mobile.Backend.csproj">
          <Project>{0B448743-182C-4ADC-8E97-7F9E7EF3A03A}</Project>
          <Name>RowingInMotion.Mobile.Backend</Name>
        </ProjectReference>
      </ItemGroup>
    </When>
  </Choose>

Note that I had to use the Choose construct to make the ProjectReference conditional, it seems just using a Condition on its item group doesn't make Visual Studio and Xamarin Studio load/ignore the project reference. It also seems that Xamarin Studio doesn't properly expand the %(RecursiveDir)... statements so the files retain their ugly filenames (not that I'd care as long as they are hidden in their _Inlined folder).

like image 1
Johannes Rudolph Avatar answered Nov 03 '22 05:11

Johannes Rudolph