UWP中WebView2的AddHostObjectToScript是否必须依赖C++ WinRT适配器?
UWP WebView2 JS与C#交互:无需WinRT C++适配器的实现方案
是否必须依赖WinRT C++适配器?
不需要。你之前遇到的报错,本质是普通C#类未满足WebView2在UWP环境下的跨语言交互要求,而非必须依赖第三方适配器。WebView2本身提供了原生的交互机制,只要遵循WinRT兼容规则即可实现JS直接调用C#代码。
方案1:使用标记[AllowForWeb]的WinRT组件
这是最直接的原生方案,利用WinRT的跨语言交互能力:
创建WinRT组件类
新建一个WinRT组件项目(或在现有UWP项目中添加符合WinRT规范的类),给类和需要暴露的方法添加[AllowForWeb]属性,同时确保参数/返回值使用WinRT兼容类型(如string、int、IAsyncOperation<T>等,避免使用普通Task<T>):using Windows.Foundation; using Windows.Foundation.Metadata; [AllowForWeb] public sealed class MessageCallWrapper { // 同步方法 public string SyncMessage(string input) { return $"C# received: {input}"; } // 异步方法(必须返回IAsyncOperation<T>) public IAsyncOperation<string> AsyncMessage(string input) { return AsyncInfo.Run(async token => { await Task.Delay(1000); return $"C# async received: {input}"; }); } }在UWP项目中绑定到WebView2
确保CoreWebView2初始化完成后,直接将实例添加为宿主对象:// 等待CoreWebView2初始化 await WebViewContainer.EnsureCoreWebView2Async(); var wrapper = new MessageCallWrapper(); WebViewContainer.CoreWebView2.AddHostObjectToScript("external", wrapper);JS端调用
直接通过全局对象调用C#方法:// 同步调用 const syncResult = window.external.SyncMessage("Hello JS"); console.log(syncResult); // 异步调用 window.external.AsyncMessage("Hello Async JS") .then(asyncResult => console.log(asyncResult));
方案2:基于消息传递的轻量交互
如果不需要直接暴露C#对象,可通过WebView2原生的消息机制实现双向交互:
C#端监听消息并响应
订阅CoreWebView2.WebMessageReceived事件,处理JS发送的消息,再通过ExecuteScriptAsync返回结果:// 初始化后绑定事件 WebViewContainer.CoreWebView2.WebMessageReceived += (sender, args) => { string jsMessage = args.WebMessageAsJson; // 解析消息(比如JSON格式) string response = $"Processed message: {jsMessage}"; // 执行JS代码返回响应 _ = WebViewContainer.CoreWebView2.ExecuteScriptAsync($"handleResponse('{response}')"); };JS端发送消息并接收响应
使用window.chrome.webview.postMessage发送消息,定义回调函数接收C#返回的结果:// 发送消息到C# window.chrome.webview.postMessage(JSON.stringify({type: "greet", content: "Hello from JS"})); // 接收C#响应 function handleResponse(response) { console.log("Received from C#:", response); }
为什么之前不用适配器会报错?
常见原因包括:
- 普通C#类未标记
[AllowForWeb],WinRT运行时无法识别为可跨语言访问的类型; - 使用了WinRT不支持的类型(如
Task<T>而非IAsyncOperation<T>); - 类未声明为
sealed(WinRT组件类必须是密封类)。
内容的提问来源于stack exchange,提问作者user2566892
相关产品推荐
相关产品推荐

