Xamarin.ios 如何将Protobuf网络与MonoTouch一起使用?

Xamarin.ios 如何将Protobuf网络与MonoTouch一起使用?,xamarin.ios,protobuf-net,Xamarin.ios,Protobuf Net,有人真的做到了吗 我尝试了建议的方法,但无论我如何生成预编译序列化程序,mtouch都无法将其复制到应用程序包中,从而导致运行时异常。我认为这是因为生成的二进制文件可能与MonoTouch不兼容 我尝试了以下方法: 1) 为了生成预编译的序列化程序,我使用了最新版本(这次是r450)中提供的iOs和Mono二进制文件 2) 我使用源代码生成了两个不同的程序集,它们是为MonoTouch构建的。第一个组件使用FEAT_SAFE符号构建;单触;没有运行时,第二个使用FEAT_SAFE符号构建;单触;

有人真的做到了吗

我尝试了建议的方法,但无论我如何生成预编译序列化程序,mtouch都无法将其复制到应用程序包中,从而导致运行时异常。我认为这是因为生成的二进制文件可能与MonoTouch不兼容

我尝试了以下方法:

1) 为了生成预编译的序列化程序,我使用了最新版本(这次是r450)中提供的iOs和Mono二进制文件

2) 我使用源代码生成了两个不同的程序集,它们是为MonoTouch构建的。第一个组件使用FEAT_SAFE符号构建;单触;没有运行时,第二个使用FEAT_SAFE符号构建;单触;专长编译器。我已经定义了符号MONOTOUCH,并且使用它的方式与使用MONODROID符号的方式相同(请参阅protobuf网络源中的CallbackAttribute.cs和Helpers.cs文件)

我使用这两个程序集,并尝试从模拟器中的MonoTouch应用程序生成预编译序列化程序


但无论我使用哪一版本的预编译序列化程序,程序集仍然不包括在应用程序包中,mtouch发出警告:“警告:应用程序包中缺少库'MyLibrary.dll',无法提取内容”,尽管事实是。

我只让它在模拟器上工作。我在VS.NET 2010上创建了自定义序列化程序集。我遇到的一个问题是,创建的IL/DLL具有错误的命名空间。我是这样做的:

model.Compile("X.Y.Serializer.MySerializer", "X.Y.Serializer.dll")
model.Compile("Taxi.ProtoBufSerializers.MQTTContractsSerializer", "MQTTContractsSerializer.dll");
但是IL是这样的:

.assembly X.Y.Serializer.MySerializer
{
   .hash algorithm 0x00008004
   .ver 0:0:0:0
}
.module X.Y.Serializer.MySerializer
也就是说,类名在程序集名称中

因此,我编写了一个perl程序来:

  • 反编译DLL->IL
  • 固定IL
  • 编译IL->DLL
以下是脚本:

#!/usr/bin/perl

# Usage: fix-protobuf-assembly assembly bad-namespace
#
# Example: fix-protobuf-assembly X.Y.Serializer.dll X.Y.Serializer.MySerializer
# X.Y.Serializer.MySerializer gets converted to X.Y.Serializer

use strict;
use File::Slurp;
use Cwd;

print "Current directory is " . getcwd() . "\n";
my $asm_file = shift || die "missing assembly file";
my $bad_ns = shift || die "missing namespace";

die "no such file '$asm_file'" if (! -f $asm_file);

my $il_file = $asm_file;
$il_file =~ s#dll$#il#;

Run("ildasm /out=$il_file $asm_file");
my $il = read_file($il_file) || die "error reading $il_file: $!";

my $ns = $bad_ns;
$ns =~ s#\.[^.]+$##;
if (($il =~ s#(\.assembly|module) $bad_ns#$1 $ns#g) == 0)
{
   die "$bad_ns not found in input dll; aborting";
}
write_file($il_file, $il);

Run("ilasm /dll $il_file");

sub Run
{
   my($command) = @_;

   warn "Running $command ...\n";
   system($command) && die "error running last command; bailing out";
}
也许我只是错过了调用Compile()的正确方法,我的hack没有必要

该程序集在Windows和iOS模拟器上运行良好。但是它随后在设备上给出了一个运行时JIT编译冲突错误。我刚刚提出了一个问题:

我确实尝试过在macw/标准控制台项目上使用MonoDevelop来首先创建序列化程序集。我有一些问题,但老实说,我很困,脾气暴躁,这可能是用户的错误,并很快决定跳转到Windows,因为我的项目有我在那里开发的其他组件


我在Windows上使用了.NET4.0项目,一切正常。我只需要创建两个仅限MT的库的轻量级版本,这样我就可以访问将被序列化的类。

我终于得到了它。看起来,当实际程序集名称与包含它的文件名不同时,mtouch不会将其包含在应用程序包中。我的情况就是这样。我生成的程序集如下所示:

model.Compile("X.Y.Serializer.MySerializer", "X.Y.Serializer.dll")
model.Compile("Taxi.ProtoBufSerializers.MQTTContractsSerializer", "MQTTContractsSerializer.dll");
因此,如果Protobuf Net将程序集名称设置为该方法的第一个参数,并将其保存在第二个参数给定的文件名中,那么mtouch将无法将其包含在应用程序包中

但是,我想保留我的名称空间,因此我修改了Protobuf Net的源代码以生成如下程序集:

model.Compile("X.Y.Serializer.MySerializer", "X.Y.Serializer.dll")
model.Compile("Taxi.ProtoBufSerializers.MQTTContractsSerializer", "MQTTContractsSerializer.dll");
  • 文件路径:作为第二个参数给定
  • 程序集名称:Path.GetFileNameWithoutExtension(路径)
  • 模块名称:Path.GetFileName(路径)
我现在没有在路径上执行任何验证,但我现在还不需要这样做

瞧,这个示例在模拟器和设备上都能工作


最后但并非最不重要的一点是,我不知道这是mtouch的行为方式还是一个bug。不过,我将针对它提交一份错误报告。

是的,我们自2012年以来一直在一个项目中使用它来提高XML序列化的性能。主要是因为我们当时的RESTFul服务无法为某些文件提供超过1MB大小的JSON。2017年的这个时候,我们现在使用JSON会容易得多,而不是为每个对象构建自定义序列化程序的额外麻烦。

请在bugzilla.xamarin.com上填写一份错误报告,并附上您正在使用的解决方案(即显示引用并使用了程序集,但touch拒绝处理它)。我听到很多关于这方面的“是”报告(即MonoTouch的成功应用)。不幸的是,我不能直接调查这件事,因为我没有mac电脑。-poupou会的-Marc你能给我指一个能让它启动并运行的人吗?@alexb现在有点老了,但我和很多人打过交道(不仅仅是那些被引用的人),我有一个直接通过电子邮件发送的号码(但我真的无法分享这些号码)。但是,由于硬件的变化,我无法确认任何当前状态。您的应用程序是否需要使用protobuf,或者您只是在寻找通用的序列化解决方案?在切换到json.net之前,我尝试了几种序列化策略,包括尝试让protobuf工作。通过在客户端和服务器端使用这个,我成功地序列化了一些非常复杂的类。这在模拟器上运行,但在设备上有问题。更多信息,请填写错误报告:),顺便说一句,您可以将自己的答案标记为“已回答”,以便通过so搜索的任何人都可以看到问题的解决方案。