首页 > 解决方案 > AOT 设备中的 Json.Net 反序列化是否需要空构造函数?

问题描述

我已经在我的项目中多次使用 Json.Net 来保存数据,并且从不担心为我的序列化类创建无参数构造函数。

现在我正在做一个适合这种情况的项目。它使用 Json.Net 序列化一些没有无参数构造函数的类,并且工作正常。但是,一位同事警告我,我很幸运从未遇到任何问题,并且ExecutionEngineException: Attempting to JIT compile method 在 iOS 构建中,该错误可能随时出现并使我的应用程序崩溃。

我看过很多关于 Json.Net 和 Constructors 或 Json.Net 和 AOT 的话题,但没有看到关于 Json.Net、Constructors 和 AOT 的话题。至少本世纪没有。

所以,我的问题是,我是否应该担心 iOS 设备中没有无参数构造函数的序列化类?

编辑:我的类有构造函数,但它们接收参数。我想知道我是否需要除它们之外没有参数的构造函数。

标签: c#unity3djson.net

解决方案


正如评论中提到的,您应该害怕的是字节码剥离,而不是有关默认构造函数数量的任何事实。

Newtonsoft.Json 实例化类型的反射部分是不可避免的,因此为了保护您的所有类免受字节码剥离,您有几个选择。


要么 1:通过link.xml文件禁用字节码剥离。例子:

<linker>
    <assembly fullname="MyAssembly">
        <type fullname="MyAssembly.MyCSharpClass" />
    </assembly>
</linker>

我发现 Unity 的官方文档分散且缺乏,所以我重写了几个文档。在此处阅读有关如何使用该link.xml文件的更多信息:https ://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/Fix-AOT-using-link.xml

^基于对 UnityLinker 和现有文档的行为进行逆向工程。如需进一步阅读,请访问:


选项 2:通过Preserve属性禁用字节码剥离。

向您的类、方法、字段、属性、事件或程序集添加属性将保证 UnityLinker 不会将其剥离。该属性必须是命名的PreserveAttribute,因此使用UnityEngine.Scripting.PreserveAttribute或您自己调用的属性PreserveAttribute将产生相同的结果。

using UnityEngine.Scripting;

[Preserve]
public class YourTypeWithSpecialConstructor
{
    public YourTypeWithSpecialConstructor(int value1, string value2)
    {
    }
}

阅读更多关于Preserve属性使用的信息:https ://docs.unity3d.com/ScriptReference/Scripting.PreserveAttribute.html (这个我没有重写:p)


选项 3:使用我发布的 Newtonsoft.Json for Unity 中的 AotHelper。

Assets Store 上的用于 Unity 的 JSON .NET 包基于 Newtonsoft.Json 8.0.3,但在撰写本文时,我目前与 Newtonsoft.Json 12.0.3 保持同步,并通过 Unity 包管理器交付给更容易保持最新状态: https ://github.com/jilleJr/Newtonsoft.Json-for-Unity#readme

它包括Newtonsoft.Json.UtilitiesAotHelper类,它不仅禁用字节码剥离,还强制编译某些类型,这在泛型方面非常有用。示例用法:

using Newtonsoft.Json.Utilities;
using UnityEngine;
 
public class AotTypeEnforcer : MonoBehaviour
{
    public void Awake()
    {
        AotHelper.Ensure(() => {
            _ = new YourGenericTypeWithSpecialConstructor<int>(0, null);
            _ = new YourGenericTypeWithSpecialConstructor<float>(0, null);
            _ = new YourGenericTypeWithSpecialConstructor<string>(null, null);
            _ = new YourGenericTypeWithSpecialConstructor<bool>(true, null);
        });
    }
}

public class YourGenericTypeWithSpecialConstructor<T>
{
    public YourGenericTypeWithSpecialConstructor(T value1, string value2)
    {
    }
}

在此处阅读有关如何使用 AotHelper 的更多信息:https ://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/Fix-AOT-using-AotHelper


推荐阅读