.NET Wasm向JavaScript传递对象的技术问题求助
我想编写如下代码,让JavaScript能够读取对象的属性:
[JSExport] [return: JSMarshalAs<JSType.Any>] internal static IEntry GetEntry(string id) { return _api.GetEntry(id); }
但这段代码出现了以下错误:
The type 'lexboxClientContracts.IEntry' is not supported by source-generated JavaScript interop. The generated source will not handle marshalling of the return value of method 'GetEntry'. For more information see https://aka.ms/dotnet-wasm-jsinterop (SYSLIB1072)
我反复查阅相关文档,仍未理解问题所在。我猜测可能需要自行序列化对象,但这似乎不太合理。
如果将返回类型改为object,代码可正常运行,但在JavaScript中会得到一个ManagedObject,我不知道该如何处理它,也找不到相关文档:
[JSExport] [return: JSMarshalAs<JSType.Any>] internal static object GetEntry(string id) { return _api.GetEntry(id); }
注:我并未实际使用Blazor,但这似乎是归类该.NET/Wasm相关内容的最佳方式。
错误原因
源生成式JavaScript互操作不支持直接返回接口类型(如IEntry)。这类互操作只能处理可直接封送的具体类型、基元类型,或符合特定规则的.NET类型。接口没有具体的字段/属性实现,代码生成器无法确定要封送哪些数据,因此抛出SYSLIB1072错误。
可行处理方案
返回具体实现类而非接口
如果_api.GetEntry(id)返回的是IEntry的具体实现(比如Entry类),直接将方法返回类型改为该具体类:[JSExport] [return: JSMarshalAs<JSType.Any>] internal static Entry GetEntry(string id) { return (Entry)_api.GetEntry(id); }只要该具体类具备公共无参构造函数、公共属性/字段,源生成器就能自动处理封送,JavaScript中会直接拿到可访问属性的普通对象。
手动序列化为JSON
若必须使用接口,或具体类无法直接封送,可手动将对象序列化为JSON字符串,在JavaScript中解析:using System.Text.Json; [JSExport] internal static string GetEntry(string id) { var entry = _api.GetEntry(id); return JsonSerializer.Serialize(entry); }JavaScript端调用后解析:
const entryJson = GetEntry('目标ID'); const entry = JSON.parse(entryJson); // 直接访问entry的属性即可处理ManagedObject
若坚持返回object得到ManagedObject,可通过.NET JS互操作机制在JavaScript中访问其属性/方法。假设IEntry有Name和Content属性,可这样操作:async function fetchEntry(id) { const managedObj = GetEntry(id); const name = await managedObj.Name; const content = await managedObj.Content; return { name, content }; }这种方式要求.NET类型的属性为公共可访问状态,但相比前两种方案,使用成本更高、性能也更差。
内容的提问来源于stack exchange,提问作者MyiEye

