c# - 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 设备中没有无参数构造函数的序列化类?
编辑:我的类有构造函数,但它们接收参数。我想知道我是否需要除它们之外没有参数的构造函数。
解决方案
正如评论中提到的,您应该害怕的是字节码剥离,而不是有关默认构造函数数量的任何事实。
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 和现有文档的行为进行逆向工程。如需进一步阅读,请访问:
- https://docs.unity3d.com/Manual/ManagedCodeStripping.html
- https://docs.unity3d.com/Manual/IL2CPP-BytecodeStripping.html
选项 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.Utilities。AotHelper类,它不仅禁用字节码剥离,还强制编译某些类型,这在泛型方面非常有用。示例用法:
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
推荐阅读
- docker - 我的 API 端点在生产中应该是什么样子?
- html - 悬停和动画在 CSS3 中都不起作用
- google-apps-script - 使用应用程序 javascript 将 Google 表格作为 .xlsx 文件下载到我的计算机
- live - 如何在 WebOS 中创建用于播放 M3U 播放列表 (IPTV) 的直播播放器?
- reactjs - 如何在 React.js 中连接 Polygon 链上的 Metamask 钱包并获取余额
- react-native - React Native - Google Sheets API 阅读问题
- angular - 在组合框列上实现虚拟不会绑定 KendoUI 角度中的最后一列
- rdbms - 如何识别没有分片键的查询的分片?
- javascript - 如何让中型视频在网站上观看无痛?
- python - 从存储在 DataFrame 中的列表中删除项目