1

我正在尝试在 MonoDroid 项目中使用 ServiceStack 进行 Json 序列化/反序列化。

我已经构建了 ServiceStack 以在 MonoDroid 环境中运行它,但现在我遇到了 JSON 反序列化的问题。

示例代码:

public class Track
{
        public string Id { get; set; }
        public string Title { get; set; }
        public string Artist { get; set; }
        public string Hash { get; set; }
        public string Type { get; set; }
    }
}
...
var track = new Track { Id = "1", Artist = "artist name", Hash = "654874", Title = "song title", Type = "mp3", };
var json = ServiceStack.Text.JsonSerializer.SerializeToString(track);
var track1 = ServiceStack.Text.JsonSerializer.DeserializeFromString<Track>(json);

在反序列化我有一个例外:未处理的异常:

System.ArgumentNullException: Argument cannot be null.
Parameter name: method

堆栈跟踪:

[External Code] 
0x5E in ServiceStack.Text.Json.JsonReader.GetParseFn at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Json\JsonReader.Generic.cs:36 C#
0x2 in ServiceStack.Text.Json.JsonTypeSerializer.GetParseFn at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Json\JsonTypeSerializer.cs:283 C#
0xF in ServiceStack.Text.Common.TypeAccessor.Create at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Common\DeserializeType.cs:146  C#
0x142 in ServiceStack.Text.Common.DeserializeType`1[[ServiceStack.Text.Json.JsonTypeSerializer, ServiceStack.Text, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetParseMethod at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Common\DeserializeType.cs:60 C#
0x43A in ServiceStack.Text.Common.JsReader`1[[ServiceStack.Text.Json.JsonTypeSerializer, ServiceStack.Text, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetParseFn at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Common\JsReader.cs:100  C#
0x6 in ServiceStack.Text.Json.JsonReader`1[[Database.Models.Track, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]..cctor at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Json\JsonReader.Generic.cs:58  C#
0x1B in ServiceStack.Text.JsonSerializer.DeserializeFromString at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\JsonSerializer.cs:33    C#

正如我所见,有:

var genericType = typeof(JsonReader<>).MakeGenericType(type);
var mi = genericType.GetMethod("GetParseFn", BindingFlags.Public | BindingFlags.Static);
parseFactoryFn = (ParseFactoryDelegate)Delegate.CreateDelegate(typeof(ParseFactoryDelegate), mi);

genericType 是“ServiceStack.Text.Json.JsonReader`1[System.String]”类型是“System.String”

所以,“mi”变量为空

有什么想法可以解决它,或者在哪里看?

谢谢。

4

1 回答 1

5

这里的问题是您在构建配置中启用了链接GetParseFn(),并且该方法被链接了,因为它没有被明确引用。

链接器是一个静态分析工具,包含在 Mono for Android 的构建过程中。它将扫描您已编译的应用程序并实际删除任何未明确引用的 .NET(或在本例中为已编译的 ServiceStack 类库)。这对减小应用程序的大小有很大帮助,但您可能会遇到问题,如此处所示。由于该GetParseFn()方法从未被显式引用(它是通过反射调用的),因此链接器不知道需要它并将其链接。

有几种方法可以处理这个问题。

  1. 完全禁用链接:您可以在项目的属性中关闭链接。一般来说,调试版本更容易关闭它,而发布版本则打开它。当然,如果您打算进行发布构建,这显然不是一个完整的解决方案。
  2. 仅链接 SDK 程序集:此选项将告诉链接器仅在 .NET BCL 和 Android SDK 上进行操作,并且不理会您的库。
  3. 使用PreserveAttribute:使用此属性,您可以告诉链接器保留您知道需要的某些部分,即使它们没有明确引用。由于 ServiceStack 是一个外部库,而不是您自己的,因此在这种情况下,这可能不是最佳解决方案。
  4. 使用Linkskip:此选项允许您指定链接器不应触及的特定程序集,允许您保持链接器打开,但只需在需要时选择退出。

就个人而言,在您的情况下,我建议您选择 Linkskip 路线。它将允许您仍然获得链接器的所有好处,但让它忽略 ServiceStack 以避免此类问题。在您的项目文件中,您最终会得到类似以下内容的内容:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <AndroidLinkMode>Full</AndroidLinkMode>
    <AndroidLinkSkip>ServiceStack.Text</AndroidLinkSkip>
</PropertyGroup>
于 2012-04-20T13:21:11.590 回答