Blazor JS互操作:如何从JS返回IJSObjectReference列表至C#?
问题与解决方案:JavaScript向C#返回对象引用列表
问题描述
从JavaScript返回THREE.js对象数组到C#时,无法直接反序列化为IJSInProcessObjectReference[]或IList<IJSInProcessObjectReference>,仅能得到指向整个JS数组的单个IJSInProcessObjectReference实例。
尝试过的代码示例:
JS端:
const myJsFunc = () => { // ... return [someJsObject, anotherJsObject]; }
C#端:
// 两种方式均无法得到预期的对象引用数组 var objectReferencesArray = js.Invoke<IJSInProcessObjectReference[]>("myJsFunc"); // 或 var objectReferencesArray = js.Invoke<IList<IJSInProcessObjectReference>>("myJsFunc");
原因分析
.NET与JavaScript的互操作默认不会自动解构JS数组,将每个元素转换为独立的IJSInProcessObjectReference实例。它会把整个JS数组视为一个单一的JS对象,仅返回指向该数组的引用,而非遍历数组元素生成多个引用。
可行解决方案
1. 从数组引用中逐个提取元素(优化临时方案)
拿到JS数组的引用后,直接在C#中通过JS的数组方法或属性获取每个元素的引用,无需来回传递解构:
// 获取整个JS数组的引用 var jsArrayRef = js.Invoke<IJSInProcessObjectReference>("myJsFunc"); // 获取数组长度 var arrayLength = jsArrayRef.Invoke<int>("length"); // 逐个提取元素引用 var objectRefs = new List<IJSInProcessObjectReference>(); for (int i = 0; i < arrayLength; i++) { // 使用JS的at()方法获取指定索引的元素,也可以用GetProperty(i.ToString()) var elementRef = jsArrayRef.Invoke<IJSInProcessObjectReference>("at", i); objectRefs.Add(elementRef); }
2. 封装扩展方法复用提取逻辑
可以封装一个扩展方法,快速将JS数组引用转换为C#的对象引用集合:
public static class JSArrayExtensions { public static IEnumerable<IJSInProcessObjectReference> GetElements(this IJSInProcessObjectReference jsArray) { if (jsArray == null) yield break; var length = jsArray.Invoke<int>("length"); for (int i = 0; i < length; i++) { yield return jsArray.Invoke<IJSInProcessObjectReference>("at", i); } } }
使用时只需一行代码:
var jsArrayRef = js.Invoke<IJSInProcessObjectReference>("myJsFunc"); var objectRefList = jsArrayRef.GetElements().ToList();
3. 修改JS函数返回包装对象(可选)
如果允许修改JS端逻辑,可以将数组包装在一个对象中,或者直接将每个元素作为独立属性返回,方便C#端直接获取:
JS端:
const myJsFunc = () => { const obj1 = someJsObject; const obj2 = anotherJsObject; // 方案A:包装数组 return { elements: [obj1, obj2] }; // 方案B:独立属性(适合元素数量固定的场景) // return { item1: obj1, item2: obj2 }; }
C#端(对应方案A):
var wrapperRef = js.Invoke<IJSInProcessObjectReference>("myJsFunc"); var elementsArray = wrapperRef.GetProperty<IJSInProcessObjectReference>("elements"); var objectRefs = elementsArray.GetElements().ToList();
内容的提问来源于stack exchange,提问作者Matheos
相关产品推荐
相关产品推荐

