2012-04-20 58 views
1

我想在MonoDroid项目中使用ServiceStack进行Json序列化/反序列化。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”

因此,有 “米” 变量为空

是否有任何想法如何解决它,或在哪里看?

谢谢。

回答

5

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

链接器是一个静态分析工具,作为Android的构建过程的Mono的一部分。它将扫描你编译的应用程序,并且实际上去掉任何没有被明确引用的.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> 
+0

这正是我的问题。我想使用** PreserveAttribute **来解决它。谢谢你的解释。 – Anton 2012-04-20 16:27:38