使用最新JSImport API语法在Blazor中通过MemoryView实现JS互操作
解决方案:Blazor JSImport 基于MemoryView的字节数组互操作
问题核心是你误解了.NET JSType.MemoryView 在JavaScript中的传递形式——它不是直接的内存指针,而是一个包含buffer(ArrayBuffer)、byteOffset和byteLength的对象,直接传入Uint8Array构造函数会导致错误解析,从而生成全零数组。
修正后的代码示例
1. C# 导入代码优化
可以直接将返回类型指定为byte[],无需用object,因为JS返回的Uint8Array会被自动封送为C#的byte[]:
[JSImport("getMessage", "SampleJS")] [return: JSMarshalAs<JSType.Promise<JSType.Uint8Array>>()] internal static partial Task<byte[]> GetWelcomeMessage([JSMarshalAs<JSType.MemoryView>] ArraySegment<byte> bytes);
如果想使用Span<byte>代替ArraySegment<byte>,代码同样适用:
[JSImport("getMessage", "SampleJS")] [return: JSMarshalAs<JSType.Promise<JSType.Uint8Array>>()] internal static partial Task<byte[]> GetWelcomeMessage([JSMarshalAs<JSType.MemoryView>] Span<byte> bytes);
2. JavaScript 模块代码修正
从传入的MemoryView对象中提取正确的ArrayBuffer、偏移量和长度来创建Uint8Array:
export async function getMessage(memoryView) { // 正确解析MemoryView为Uint8Array const receivedData = new Uint8Array(memoryView.buffer, memoryView.byteOffset, memoryView.byteLength); console.log("接收到的字节数据:", receivedData); // 这里可以添加自定义数据处理逻辑,比如模拟修改 receivedData[0] = receivedData[0] ^ 0x01; return await new Promise((resolve) => { setTimeout(() => { // 返回处理后的Uint8Array,C#端会自动转换为byte[] resolve(receivedData); }, 2000); }); }
3. 使用示例简化
byte[] sampleData = Encoding.UTF8.GetBytes("Hello from C#"); // 如果用ArraySegment byte[] resultBytes = await GetWelcomeMessage(new ArraySegment<byte>(sampleData)); // 如果用Span // byte[] resultBytes = await GetWelcomeMessage(sampleData.AsSpan()); string message = Encoding.UTF8.GetString(resultBytes); Console.WriteLine($"从JS返回的数据: {message}");
关键注意事项
- 共享内存特性:通过MemoryView传递的内存是共享的,JS中修改
Uint8Array会直接修改C#端的原始数组。如果不想修改原始数据,需要先复制一份:const copiedData = Uint8Array.from(receivedData); - 版本要求:该特性仅支持.NET 7及以上版本的Blazor WebAssembly。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

