<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      抽離BlazorWebview中的.Net與Javascript的互操作庫(kù)

      做這個(gè)的目的是想使用 Blazor 中的 Javascript 與 C#中的互操作,但是又不需要加載 Blazor 整個(gè)類庫(kù),另外 BlazorWebView 組件沒有支持直接通過 Http 協(xié)議加載 web 頁(yè)面,調(diào)試的時(shí)候需要先把后端接口寫好,然后前端打包,然后一起調(diào)試,感覺很麻煩,因此想能不能把互操作這部分功能單獨(dú)抽離出來(lái)。后面研究了 asp.net core 關(guān)于這部分的源碼,發(fā)現(xiàn)可行,于是抽離出來(lái)了這部分功能,由于 Microsoft.JSInterop 這個(gè) nuget 包不支持.Net Framework,順便還移植到了.Net Framework 平臺(tái)。正常使用已將近 1 年。現(xiàn)寫文章記錄回憶一下,也給有需要的朋友研究研究。

      一、如何使用

      帶互操作的 WebView 已經(jīng)支持了.Net Framework 下的 WPF 和 MAUI 中的安卓端。工作上需要這兩個(gè),其他平臺(tái)暫時(shí)不支持。官方 nuget 倉(cāng)庫(kù)上,上傳了最近一個(gè) WPF 的版本。

      1、安裝

      使用 nuget 包管理器搜索HSoft.WebView.NetFramework.WPF然后安裝即可。

      2、引入 Webview 組件

      打開一個(gè) xaml 文件,引入組件命名空間

      xmlns:wpf="clr-namespace:HSoft.WebView.NetFramework.WPF;assembly=HSoft.WebView.NetFramework.WPF"
      

      使用組件

      <Window
          x:Class="TestWVF.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:local="clr-namespace:TestWVF"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          xmlns:wpf="clr-namespace:HSoft.WebView.NetFramework.WPF;assembly=HSoft.WebView.NetFramework.WPF"
          Title="MainWindow"
          Width="800"
          Height="450"
          mc:Ignorable="d">
          <Grid>
              <wpf:WebView Source="http://localhost:5173" />
          </Grid>
      </Window>
      
      

      如果是開發(fā)模式下,Source 填寫你的前端服務(wù)器地址,生產(chǎn)環(huán)境,則一般填寫http://0.0.0.0/index.html。項(xiàng)目新增一個(gè) wwwroot 目錄,然后編輯項(xiàng)目文件,添加如下節(jié)點(diǎn),以便把網(wǎng)頁(yè)文件嵌入程序集。

      <?xml version="1.0" encoding="utf-8"?>
      <Project>
          <!--...-->
          <ItemGroup>
          <EmbeddedResource Include="wwwroot\**\*">
          </EmbeddedResource>
          </ItemGroup>
          <!--...-->
      </Project>
      

      你的網(wǎng)頁(yè)啟動(dòng)頁(yè)面位置如果是這樣的wwwroot\index.html,則對(duì)應(yīng)的Source為http://0.0.0.0/index.html。

      二、原理

      開門見山,借助 Microsoft.JSInterop 和前端的@microsoft/dotnet-js-interop 包,便可實(shí)現(xiàn) Javascript和C#的互操作。這兩個(gè)包定義除信息傳遞通道之外的所有必要的信息。因此,我們只需要把傳送通道給補(bǔ)充上就可以正常工作。直接使用 Webview2 組件的 IPC 通訊,也就是 chrome.webview.postMessage 和 chrome.webview.addEventListener("message", (e: any))來(lái)發(fā)送和接受消息。

      1、Javascript

      在前端引入@microsoft/dotnet-js-interop 包。使用 DotNet.attachDispatcher 創(chuàng)建 dispatcher。

      import { DotNet } from "@microsoft/dotnet-js-interop";
      
      let dispatcher: DotNet.ICallDispatcher;
      dispatcher = DotNet.attachDispatcher({
        sendByteArray: sendByteArray,
        beginInvokeDotNetFromJS: beginInvokeDotNetFromJS,
        endInvokeJSFromDotNet: endInvokeJSFromDotNet,
      });
      

      主要實(shí)現(xiàn)三個(gè)函數(shù),這三個(gè)函數(shù)使用 postMessage 發(fā)送消息到.Net 端。

      • sendByteArray(當(dāng)傳遞參數(shù)中含有字節(jié)數(shù)組的時(shí)候調(diào)用這個(gè))
      • beginInvokeDotNetFromJS(從 JS 調(diào)用.Net 方法)
      • endInvokeJSFromDotNet(從.Net 調(diào)用 JS,JS 這邊處理完畢需要調(diào)用此方法告知.Net 調(diào)用完畢)

      sendByteArray

      function sendByteArray(id: number, data: Uint8Array): void {
        const dataBase64Encoded = base64EncodeByteArray(data);
        (window as any).chrome.webview.postMessage([
          "ReceiveByteArrayFromJS",
          id,
          dataBase64Encoded,
        ]);
      }
      

      beginInvokeDotNetFromJS

      function beginInvokeDotNetFromJS(
        callId: number,
        assemblyName: string | null,
        methodIdentifier: string,
        dotNetObjectId: number | null,
        argsJson: string
      ): void {
        console.log("beginInvokeDotNetFromJS");
        (window as any).chrome.webview.postMessage([
          "beginInvokeDotNetFromJS",
          callId ? callId.toString() : null,
          assemblyName,
          methodIdentifier,
          dotNetObjectId || 0,
          argsJson,
        ]);
      }
      

      endInvokeJSFromDotNet

      function endInvokeJSFromDotNet(
        callId: number,
        succeeded: boolean,
        resultOrError: any
      ): void {
        console.log("beginInvokeDotNetFromJS");
        (window as any).chrome.webview.postMessage([
          "endInvokeJSFromDotNet",
          callId ? callId.toString() : null,
          succeeded,
          resultOrError,
        ]);
      }
      

      工具函數(shù)

      function base64EncodeByteArray(data: Uint8Array) {
        // Base64 encode a (large) byte array
        // Note `btoa(String.fromCharCode.apply(null, data as unknown as number[]));`
        // isn't sufficient as the `apply` over a large array overflows the stack.
        const charBytes = new Array(data.length);
        for (var i = 0; i < data.length; i++) {
          charBytes[i] = String.fromCharCode(data[i]);
        }
        const dataBase64Encoded = btoa(charBytes.join(""));
        return dataBase64Encoded;
      }
      
      // https://stackoverflow.com/a/21797381
      // TODO: If the data is large, consider switching over to the native decoder as in https://stackoverflow.com/a/54123275
      // But don't force it to be async all the time. Yielding execution leads to perceptible lag.
      function base64ToArrayBuffer(base64: string): Uint8Array {
        const binaryString = atob(base64);
        const length = binaryString.length;
        const result = new Uint8Array(length);
        for (let i = 0; i < length; i++) {
          result[i] = binaryString.charCodeAt(i);
        }
        return result;
      }
      

      接收來(lái)自.Net 的消息并處理

      (window as any).chrome.webview.addEventListener("message", (e: any) => {
        var ob = JSON.parse(e.data);
      
        switch (ob[0]) {
          case "EndInvokeDotNet": {
            dispatcher.endInvokeDotNetFromJS(ob[1], ob[2], ob[3]);
            break;
          }
          case "BeginInvokeJS": {
            dispatcher.beginInvokeJSFromDotNet(ob[1], ob[2], ob[3], ob[4], ob[5]);
            break;
          }
          case "SendByteArrayToJS": {
            let id = ob[1];
            let base64Data = ob[2];
            const data = base64ToArrayBuffer(base64Data);
            dispatcher.receiveByteArray(id,data);
            break;
          }
          default: {
            console.error(`不支持的消息類型${e.data}`);
          }
        }
      });
      

      window 對(duì)象增加屬性

      (window as any)["DotNet"] = DotNet;
      export { DotNet };
      

      完整代碼

      import { DotNet } from "@microsoft/dotnet-js-interop";
      
      let dispatcher: DotNet.ICallDispatcher;
      dispatcher = DotNet.attachDispatcher({
        sendByteArray: sendByteArray,
        beginInvokeDotNetFromJS: beginInvokeDotNetFromJS,
        endInvokeJSFromDotNet: endInvokeJSFromDotNet,
      });
      
      
      function sendByteArray(id: number, data: Uint8Array): void {
          const dataBase64Encoded = base64EncodeByteArray(data);
          (window as any).chrome.webview.postMessage([
            "ReceiveByteArrayFromJS",
            id,
            dataBase64Encoded,
          ]);
        }
      
      function beginInvokeDotNetFromJS(
        callId: number,
        assemblyName: string | null,
        methodIdentifier: string,
        dotNetObjectId: number | null,
        argsJson: string
      ): void {
        console.log("beginInvokeDotNetFromJS");
        (window as any).chrome.webview.postMessage([
          "beginInvokeDotNetFromJS",
          callId ? callId.toString() : null,
          assemblyName,
          methodIdentifier,
          dotNetObjectId || 0,
          argsJson,
        ]);
      }
      
      function endInvokeJSFromDotNet(
        callId: number,
        succeeded: boolean,
        resultOrError: any
      ): void {
        console.log("beginInvokeDotNetFromJS");
        (window as any).chrome.webview.postMessage([
          "endInvokeJSFromDotNet",
          callId ? callId.toString() : null,
          succeeded,
          resultOrError,
        ]);
      }
      
      
      function base64EncodeByteArray(data: Uint8Array) {
        // Base64 encode a (large) byte array
        // Note `btoa(String.fromCharCode.apply(null, data as unknown as number[]));`
        // isn't sufficient as the `apply` over a large array overflows the stack.
        const charBytes = new Array(data.length);
        for (var i = 0; i < data.length; i++) {
          charBytes[i] = String.fromCharCode(data[i]);
        }
        const dataBase64Encoded = btoa(charBytes.join(""));
        return dataBase64Encoded;
      }
      // https://stackoverflow.com/a/21797381
      // TODO: If the data is large, consider switching over to the native decoder as in https://stackoverflow.com/a/54123275
      // But don't force it to be async all the time. Yielding execution leads to perceptible lag.
      function base64ToArrayBuffer(base64: string): Uint8Array {
          const binaryString = atob(base64);
          const length = binaryString.length;
          const result = new Uint8Array(length);
          for (let i = 0; i < length; i++) {
            result[i] = binaryString.charCodeAt(i);
          }
          return result;
        }
      (window as any).chrome.webview.addEventListener("message", (e: any) => {
          var ob = JSON.parse(e.data);
      
          switch (ob[0]) {
            case "EndInvokeDotNet": {
              dispatcher.endInvokeDotNetFromJS(ob[1], ob[2], ob[3]);
              break;
            }
            case "BeginInvokeJS": {
              dispatcher.beginInvokeJSFromDotNet(ob[1], ob[2], ob[3], ob[4], ob[5]);
              break;
            }
            case "SendByteArrayToJS": {
              let id = ob[1];
              let base64Data = ob[2];
              const data = base64ToArrayBuffer(base64Data);
              dispatcher.receiveByteArray(id,data);
              break;
            }
            default: {
              console.error(`不支持的消息類型${e.data}`);
            }
          }
        });
      
      (window as any)["DotNet"] = DotNet;
      export { DotNet };
      
      
      

      2、.Net

      在.Net 這邊類似,使用 WebView2 的 WebMessageReceived 事件和 PostWebMessageAsString 方法來(lái)與前端通訊,后端通過 WebMessageReceived 處理來(lái)自前端的beginInvokeDotNetFromJSendInvokeJSFromDotNetReceiveByteArrayFromJS的消息,然后通過靜態(tài)類 DotNetDispatcher 中的 BeginInvokeDotNet、EndInvokeJS、ReceiveByteArray 來(lái)處理,通過繼承 JSRuntime,實(shí)現(xiàn) BeginInvokeJS、EndInvokeDotNet、SendByteArray 方法,通過 PostWebMessageAsString 發(fā)送數(shù)據(jù)到前端。在這里不給出代碼,感興趣的直接查看 https://github.com/HekunX/wvf 倉(cāng)庫(kù)。

      posted @ 2025-04-01 15:58  白煙染黑墨  閱讀(9586)  評(píng)論(4)    收藏  舉報(bào)
      主站蜘蛛池模板: 色色97| 狠狠躁天天躁中文字幕无码| 日韩一区二区三在线观看| 天堂中文8资源在线8| 亚洲国产欧美在线人成| 亚洲成av人片天堂网无码 | 97国产露脸精品国产麻豆| 久人人爽人人爽人人片av| 欧美肥老太wbwbwbb| 日韩人妻一区中文字幕| 国产女高清在线看免费观看| 国产精品午夜福利导航导| 日韩av日韩av在线| 久久精品一区二区三区综合| 亚洲伊人成无码综合网| 龙口市| 日韩精品中文字幕人妻| 精品国产欧美一区二区三区在线| 久久亚洲中文字幕伊人久久大| 国产av午夜精品福利| 精品国产欧美一区二区三区在线| 肥大bbwbbw高潮抽搐| 免费看婬乱a欧美大片| 一本色道久久东京热| 亚洲a成人片在线观看| 精品一日韩美女性夜视频| 久久这里只精品国产免费9| 亚洲精品三区四区成人少| 少妇特黄a一区二区三区| 少妇激情一区二区三区视频小说 | 国产一区二区日韩经典| 久久国产精品老人性| 一区二区免费高清观看国产丝瓜| 99久久亚洲综合精品成人网| 亚洲午夜天堂| 无码人妻久久一区二区三区app| 亚洲日本精品一区二区| 漯河市| 精品国产成人国产在线视| 久久综合久久美利坚合众国 | 久久99精品久久久久久 |