使用带有 F# 和 ReactiveUI 的 Xamarin Android 时出现运行时错误

Runtime error using Xamarin Android with F# and ReactiveUI

我创建了一个使用 F# 和 ReactiveUI 的 Xamarin Android 项目。

加载我的仪表板时,我在此代码段的 inherit 行遇到运行时异常(MissingMethodException 类型):

type DashboardViewModel(?host: IScreen) =
    inherit ReactiveViewModel()
    let host = LocateIfNone host
    member __.Title with get() = "Dashboard"
    interface IRoutableViewModel with
        member __.HostScreen = host
        member __.UrlPathSegment = "Dashboard"

错误消息显示为

Method 'Microsoft.FSharp.Quotations.FSharpExpr.Deserialize40' not found.

ReactiveViewModel 类型是 ReactiveObject 的薄包装:

type ReactiveViewModel() as this =
    inherit ReactiveObject()
    let mutable message = noMessage
    let uiContext = SynchronizationContext.Current
    member __.SyncContext with get() = uiContext
    member this.Message 
        with get() = message 
        and set(value) = 
            this.RaiseAndSetIfChanged(&message, value, "Message") |> ignore
            if message <> noMessage then this.RaiseAndSetIfChanged(&message, noMessage, "Message") |> ignore
    member val MessageSent = 
        this.WhenAnyValue(toLinq <@ fun vm -> vm.Message @>).ObserveOn(RxApp.MainThreadScheduler).Where(fun m -> m <> noMessage) with get

该项目是开源的:目前,它包含的内容很少。它可以在 https://github.com/SpiegelSoft/Astrid.

找到

我已在 Xamarin 错误跟踪器上提交错误:https://bugzilla.xamarin.com/show_bug.cgi?id=51000

有没有我可以自己实施的已知修复程序,以便我可以自行关闭错误?

更新 1

这个周末我一直在调查这个问题。

加载的FSharp.Core版本卡在过时版本2.3.98.1上。这对应于

中的 FSharp.Core.dll 文件

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0

我已尝试删除此版本并加载 NuGet 包 FSharp.Core;然而,当我构建 Android 项目时,路径总是恢复到参考程序集路径中的过时文件。

有没有办法覆盖这种行为?

更新 2

替换Reference Assemblies路径下的FSharp.Core.dll文件可以解决问题,但这是一个非常不理想的橡皮膏,我不能要求我的用户应用。理想情况下,我想找到一种方法来防止 .Droid 项目从 GAC 而不是 NuGet 包加载 FSharp.Core

前几天我 运行 遇到了一个非常相似的问题。我的 android 应用程序引用了 Profile7 F# PCL 库,它使用了 List.unfold,我相信它是在 F# 4 中引入的。当我在我的应用程序中使用该库时,我看到类似于您所看到的 MissingMethodException。 Xamarin 在创建新的 Android 应用程序时默认引用的 FSharp.Core 版本没有这个更新的方法。我通过编辑应用程序的 .fsproj 文件以删除对 FSharp.Core 的原始引用并将其替换为对较新版本的引用(我 copy/pasted 来自 PCL.fsproj 文件)。它看起来像这样:

<Reference Include="FSharp.Core">
   <Name>FSharp.Core</Name>
   <Private>True</Private>
   <AssemblyName>FSharp.Core.dll</AssemblyName>
   <HintPath>$(MSBuildExtensionsPath32)\..\Reference Assemblies\Microsoft\FSharp\.NETCore$(TargetFSharpCoreVersion)\FSharp.Core.dll</HintPath>
</Reference> 

我惊讶地发现这似乎解决了我的问题。我不确定我是否会 运行 解决其他问题,但如果你还没有尝试的话可能值得一试。

更新 如果这不能立即奏效,请按照 Rob Lyndon 的回答中的步骤顺序进行操作。

这似乎已被 GitHub 提交

修复

https://github.com/xamarin/xamarin-android/commit/df41af046000556ed82f638e8041b7f718966a92

从框架程序集列表中删除 FSharp.Core,并允许在不替换 NuGet FSharp.Core 程序集的情况下构建项目。

在将此修复程序发布到 SDK 之前,有一个解决方法。 user3850711 提交的答案有效,但您需要按特定顺序应用更改,否则引用将在构建过程中被覆盖。

  1. 删除对 FSharp.Core 的现有引用。
  2. 安装或重新安装 FSharp.Core NuGet 包。
  3. 卸载项目并将 <HintPath>packages\FSharp.Core.4.0.0.1\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll</HintPath> 添加到 FSharp.Core 项目引用。