如何获取Firestore中键名动态的文档字段值?
问题描述
我使用Plugin.CloudFirestore,平时会用一个类来映射文档获取值,示例代码如下:
public class FirestoreDoc { public string key { get; set; } } firestoreDoc.ToObject<FirestoreDoc>().key;
现在遇到一个特殊场景:文档的键名由应用用户动态添加,虽然能获取到键名,但无法给类动态添加成员,不知道该怎么获取对应的值?
补充说明
要获取的字段类型是array,存储的是其他数据库文档的reference。我尝试了以下代码:
var referenceList = firestoreDoc.Data[customKey];
这行代码能成功获取到指定键的值,但存在两个问题:
- 无法遍历获取到的列表值;
- 列表值的类型为
string而非IDocumentReference,无法调用GetAsync()方法获取引用的文档。
针对第二个问题,我尝试强制转换:
var referenceList = (List<IDocumentReference>)firestoreDoc.Data[customKey];
但转换时抛出错误:
System.InvalidCastException: 'Specified cast is not valid.'
解决方案
正确转换并遍历文档引用列表
因为firestoreDoc.Data[customKey]返回的集合类型并非直接是List<IDocumentReference>,而是Plugin内部的集合实现,所以不能直接强制类型转换,需要先转为可枚举对象再逐个处理:
// 第一步:将动态获取的值转为可枚举的对象集合 var rawCollection = firestoreDoc.Data[customKey] as IEnumerable<object>; if (rawCollection != null) { // 第二步:逐个将元素转换为IDocumentReference,过滤掉无效值 var docReferences = rawCollection .Select(item => item as IDocumentReference) .Where(refObj => refObj != null) .ToList(); // 第三步:遍历并调用GetAsync()获取引用文档 foreach (var docRef in docReferences) { var targetDoc = await docRef.GetAsync(); // 在这里处理获取到的目标文档 var docData = targetDoc.ToObject<YourTargetDocClass>(); } }
特殊情况处理
如果上述as转换失败(比如不同平台的实现差异),可以尝试针对原生类型做适配处理:
var rawCollection = firestoreDoc.Data[customKey] as IEnumerable; var docReferences = new List<IDocumentReference>(); if (rawCollection != null) { foreach (var item in rawCollection) { // 直接匹配接口类型 if (item is IDocumentReference docRef) { docReferences.Add(docRef); } // 针对Android平台原生引用的适配示例 // else if (item is Android.Gms.Firestore.DocumentReference androidRef) // { // docReferences.Add(new DocumentReference(androidRef)); // } // 针对iOS平台原生引用的适配示例 // else if (item is Firebase.Firestore.FIRDocumentReference iosRef) // { // docReferences.Add(new DocumentReference(iosRef)); // } } }
关键说明
- 避免直接强制转换
List<IDocumentReference>:Data属性返回的动态值对应的集合类型可能是只读集合或Plugin自定义的数组包装,强制转换会触发类型不匹配异常。 - 逐个转换更安全:通过
as操作符转换可以避免转换失败抛出异常,同时过滤掉无效的非引用类型元素。
内容的提问来源于stack exchange,提问作者Costas
相关产品推荐
相关产品推荐

