You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mac版VS 2017社区版Xamarin.iOS开发模型字段丢失问题求助

问题原因与解决方案

这个问题是Xamarin.iOS链接器(Linker)的优化行为导致的,具体来拆解下:

为什么会出现这种奇怪的现象?

Xamarin.iOS的链接器会自动移除它判定为“未被使用”的代码,以此来减小最终应用的体积。而你用来序列化的Json.NET是通过反射来读取类属性的——但链接器无法识别反射调用的依赖关系,所以如果你的iOS项目代码里没有直接访问SearchRequest的某个属性(比如FullName),链接器会认为这个属性的get/set方法是无用的,直接把它们从编译后的代码里移除了。

这就完美解释了你遇到的所有情况:

  • 当你没在iOS项目里访问FullName时,PCL里序列化出来的对象只有EmailAddress(因为你访问过它),甚至是空对象{};
  • 当你添加Console.WriteLine(searchRequest.FullName)后,链接器看到这个属性被直接引用了,就会保留它的访问器,Json.NET就能正常序列化所有属性;
  • 哪怕你在await client.Search(...)之后访问属性,链接器在编译阶段就已经决定了要保留哪些成员,所以同样能让序列化正常工作。

如何解决这个问题?

有几种可靠的方法可以避免链接器误删模型类的属性:

1. 使用[Preserve]特性标记模型类

这是最推荐的方法,直接告诉链接器保留类的所有成员。你需要先引入Foundation命名空间,然后在类或属性上添加特性:

using Foundation;

// 标记整个类,保留所有成员
[Preserve(AllMembers = true)]
public class SearchRequest {
    public string FullName {get; set;}
    public string EmailAddress {get;set;}
}

或者单独标记每个属性:

using Foundation;

public class SearchRequest {
    [Preserve]
    public string FullName {get; set;}
    [Preserve]
    public string EmailAddress {get;set;}
}

2. 修改链接器行为

在iOS项目的属性设置里调整链接器的优化范围:

  • 右键你的Xamarin.iOS项目 → 属性 → iOS Build
  • 在“链接器行为”(Linker Behavior)下拉菜单中选择仅链接SDK程序集(Link SDK assemblies only)
  • 这样链接器只会优化系统SDK的代码,不会碰你自己写的PCL模型类,缺点是应用体积会稍微大一点。

3. 添加“占位”代码强制保留属性

如果你不想用特性或修改链接器设置,可以在模型类里加一个空方法,里面访问所有属性,让链接器认为这些属性被使用了:

public class SearchRequest {
    public string FullName {get; set;}
    public string EmailAddress {get;set;}

    // 链接器会认为这些属性被引用,不会移除
    public void PreserveMembers() {
        var _ = FullName;
        var __ = EmailAddress;
    }
}

然后在iOS项目里调用这个方法:

SearchRequest searchRequest = new SearchRequest { EmailAddress = "sample@domain.com", FullName = "Sample Full Name" };
searchRequest.PreserveMembers(); // 调用后链接器会保留所有属性
var result = await client.Search(searchRequest);

4. 配合Json.NET的JsonProperty特性

虽然单独用JsonProperty不一定能阻止链接器,但结合Preserve特性会更稳妥,同时明确指定序列化的字段名:

using Foundation;
using Newtonsoft.Json;

[Preserve(AllMembers = true)]
public class SearchRequest {
    [JsonProperty("FullName")]
    public string FullName {get; set;}
    [JsonProperty("EmailAddress")]
    public string EmailAddress {get;set;}
}

验证问题根源

你可以检查当前项目的链接器设置:如果是链接所有程序集(Link all assemblies),那大概率就是这个问题导致的。Debug模式下默认可能是“不链接”或“仅链接SDK”,所以有时候不会出现,但Release模式下默认是“链接所有程序集”,很容易触发这个问题。

内容的提问来源于stack exchange,提问作者Moamen Naanou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:35:28