【问题标题】:What is wrong with XML Serialization of a lib class with IL2CPP?使用 IL2CPP 对 lib 类进行 XML 序列化有什么问题?
【发布时间】:2019-05-28 13:48:39
【问题描述】:

在 Unity 项目上将脚本后端从 Mono 设置为 IL2CPP 后,当它运行 lib 类(来自 dll 库)的 XML 反序列化时,它会在运行时引发异常。

Google Play 很快将不再接受不包含 64 位版本的构建。这意味着在 Unity 中我们必须从 Mono 切换到 IL2CPP。目标设备是 Android 设备。

我们尝试使用各种版本的 .Net Framework 构建 dll 库。我们还尝试在默认构造函数(无参数)中添加一些指令。然后我们在反序列化调用之前使用构造函数,以防在构建时进行剥离。我们试图通过代码强制禁用剥离级别,但我们不知道它是否有效。

这是发生问题的类,反序列化失败。

namespace Api.Common.Licence
{
    [XmlRoot(ElementName = "DeviceLicenceFile")]
    public class DeviceLicenceFile
    {
        public DeviceLicenceFile()
        {
            //Email = null; //tried that for an example but is usually empty
        }

        [XmlElement(ElementName = "Email")]
        public string Email { get; set; }
        [...]
    }
}

这是我的序列化函数

public static T Deserialize<T>(string text)
{
    var serializer = new XmlSerializer(typeof(T));
    T obj = (T) (serializer.Deserialize(new StringReader(text)));
    return obj;
}

一切都适用于 Mono 但使用 IL2CPP,它会引发以下错误 => “System.InvalidOperationException:出现反映类型'Api.Common.Licence.DeviceLicenceFile'的错误。---> System.InvalidOperationException:Api.Common.Licence.DeviceLicenceFile 无法序列化,因为它没有默认的公共构造函数” 当然,我们有一个无参数的构造函数。

编辑:我们正在使用 Unity 2018.4

【问题讨论】:

  • 您是否广泛使用 XML 序列化?如果没有,这样的代码很容易被替换为只使用XElementXmlReader 的“手动”代码。框架的 XML 序列化在后台有很多反射/代码生成,这对 AOT 编译来说是一个特殊的挑战。
  • @JeroenMostert 我想如果不能解决这个问题,我们会这样做。这似乎是 Unity 上的一个错误,但他们说它已被修复:issuetracker.unity3d.com/issues/…
  • @Shirosamus 上面的三个 cmets 来自我和我认识的人 ;) 这对我来说也不是固定的......但是那里也有一个解决方法:切换 Api Compatibility Level 在播放器设置为.Net Standard 2.0。这仍然会在调试时引发异常(关于编码和 CP1252),但您可以忽略它,因为它会按预期继续
  • 我不能只更改 API 兼容性,因为某些功能需要 4.0。但我暂时使用 XmlReader 作为临时解决方案。
  • 你能用DataContractSerializer吗?如果您使用数据协定属性标记您的类,则不需要无参数构造函数(甚至不需要调用)。请注意,DataContractSerializer 不支持 XML 属性或单级列表序列化,因此如果您的 XML 架构包含这些,则不能使用它。

标签: c# xml unity3d deserialization il2cpp


【解决方案1】:

这里的问题可能是 IL2CPP 在构建期间删除了 DeviceLicenceFile 类,因为它仅通过泛型/反射使用。 (IL2CPP 进行托管代码剥离以减少二进制大小/构建时间。)

您可以将整个程序集(或仅该类型)添加到一个名为 link.xml 的文件中,该文件必须放在您的 Assets 目录的根目录中,这将告诉 Unity 不要删除该类。有关更多信息,请参阅此处的文档:https://docs.unity3d.com/Manual/IL2CPP-BytecodeStripping.html - 您将在“使用反射时如何处理剥离”部分中看到所需文件内容的示例。

【讨论】:

  • 不是这样的。我们仍然可以调用该类并设置一个属性,例如(之前或之后),但它不会改变任何异常。类存在,但构造函数不存在。我从头开始,错误仍然存​​在。我把它报告给了unity。 xml 序列化和 IL2CPP 之前似乎发生了一些问题。待续……
  • 您是否尝试使用 Preserve="all" 添加整个程序集?代码剥离器甚至会删除一个未使用的构造函数 - 可能会发生您从代码中使用的构造函数可以正常工作,而另一个则不能。
  • 当然,IL2CPP 的 bug 还是很多的,所以如果 ^ 不能解决的话,这完全是一种选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多