Unity Firebase项目IL2CPP构建时List泛型运行时上下文获取错误如何解决
报错根本原因
这个错误是IL2CPP的AOT编译机制限制导致的,和你调用方法时是否指定泛型参数无关:
- Unity编辑器运行时采用Mono JIT编译模式,可在运行时动态生成所需的泛型类型实例代码,所以不会触发错误
- IL2CPP采用AOT提前编译模式,必须在构建阶段就生成所有后续要用到的闭合泛型类型的元数据和代码。你的自定义
FirestoreList是双层泛型类,同时继承了泛型List并实现了泛型接口,Firebase的Firestore序列化器会通过反射访问该类的构造函数完成反序列化,编译器无法提前感知到需要为你用到的具体泛型参数组合(比如FirestoreList<User_FirestoreData, User>)生成构造函数的代码,就会抛出找不到运行时泛型上下文的错误。
更优解决方案
方案1:强制AOT编译指定泛型实例
如果不想改动原有FirestoreList的代码,可以新增一个静态辅助类,用[Preserve]属性强制编译器提前编译你业务中用到的所有FirestoreList具体类型:
using UnityEngine.Scripting; using System.Collections.Generic; public static class FirestoreAotHelper { [Preserve] public static readonly FirestoreList<User_FirestoreData, User> _userListInstance = new FirestoreList<User_FirestoreData, User>(new List<User>()); // 后续新增其他泛型参数组合的FirestoreList,都在这里加一行对应的声明即可 }
该方案成本最低,原有业务代码不需要做任何修改。
方案2:改用组合模式替代继承泛型List
直接继承泛型List很容易导致第三方序列化库反射时触发泛型上下文问题,改成组合模式把List作为内部字段,可从根本上避免这类问题:
using System.Collections.Generic; using Firebase.Firestore; [FirestoreData] public class FirestoreList<FirestoreData, PlainData> : IConvertToPlainData<List<PlainData>> where FirestoreData : IConvertToPlainData<PlainData> where PlainData : IConvertToFirestore<FirestoreData> { [FirestoreProperty] public List<FirestoreData> Items { get; set; } = new List<FirestoreData>(); public FirestoreList() { } public FirestoreList(List<PlainData> plainDataList) { foreach (var plainData in plainDataList) { Items.Add(plainData.ToFirestoreData()); } } public List<PlainData> ToPlainData() { var convertedPlainDataList = new List<PlainData>(); foreach (var firestoreData in Items) { convertedPlainDataList.Add(firestoreData.ToPlainData()); } return convertedPlainDataList; } }
修改后业务侧的调用只需要调整对应属性的访问路径,不需要显式指定泛型参数,比你当前用的扩展方法写法更简洁,也不需要每次新增泛型组合都修改AOT辅助类。
内容的提问来源于stack exchange,提问作者Lotan
相关产品推荐
相关产品推荐

