You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:52:45