我已经在项目中使用Json.Net很多次来保存数据,而且从不担心为序列化类创建无参数构造函数。
现在我正在做一个适合这种情况的项目。它使用Json.Net序列化了一些没有无参数构造函数的类,并且运行良好。然而,一位同事警告我,我很幸运从未遇到过任何问题,并且在iOS构建中,ExecutionEngineException: Attempting to JIT compile method
错误可能随时出现并使我的应用程序崩溃。
我看过很多关于Json.Net和Constructors或Json.Net与AOT的主题,但没有看到关于Json.Net、Constructors和AOT的内容。至少本世纪没有。
所以,我的问题是,我应该担心iOS设备中没有无参数构造函数的序列化类吗?
EDIT:我的类有构造函数,但它们接收参数。我想知道我是否需要没有参数的构造函数。
如注释中所述,您应该害怕的只是字节码剥离,而不是关于默认构造函数数量的任何事实。
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上的JSON.NET for Unity包基于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