當前位置: 妍妍網 > 碼農

如何在瀏覽器中執行 .NET

2024-03-25碼農


概述: 本文將討論如何用最簡單的術語在網站上執行 C# 程式碼。半技術講座我使用了 wasm-tools-net7,這是一個基於 wasm-tools 的工作負載,沒有包含任何額外的包。我的重點是簡單性和主要主題。徹底了解該主題可提供完成所有其他任務所需的資訊。如何工作?WebAssembly 工作原理:序列圖建立演示建立計畫我用的是net7,但這取決於你。Dotnet new console -o WASM_Demo cd WASM_Demo Dotnet workload install wasm-tools-net7此時,需要對 csproj 檔進行修改。Project Sdk=Mi

本文將討論如何用最簡單的術語在網站上執行 C# 程式碼。

半技術講座

我使用了 wasm-tools-net7,這是一個基於 wasm-tools 的工作負載,沒有包含任何額外的包。我的重點是簡單性和主要主題。徹底了解該主題可提供完成所有其他任務所需的資訊。

如何工作?

WebAssembly 工作原理:序列圖

建立演示

建立計畫

  • 我用的是net7,但這取決於你。

  • Dotnet new console -o WASM_Demo
    cd WASM_Demo
    Dotnet workload install wasm-tools-net7

    此時,需要對 csproj 檔進行修改。

    <Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
    <WasmMainJSPath>main.js</WasmMainJSPath>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    </PropertyGroup>
    <ItemGroup>
    <WasmExtraFilesToDeploy Include="index.html"/>
    <WasmExtraFilesToDeploy Include="main.js"/>
    </ItemGroup>
    </Project>


    我們添加了什麽:

  • RuntimeIdentifier (wasm-tools 需要)

  • WasmMainJSPath (wasm-tools 需要)

  • AllowUnsafeBlocks(JSExportAttribute 需要不安全的程式碼)

  • ItemGroup (Include as resource)

  • 匯入 index.html

  • 匯入main.js

  • 返回到program.cs檔,需要考慮某些規則。

  • 類必須是公共的和部份的。

  • 函式必須是公共的和靜態的,並且必須使用 [JSExport] 進行內容化。

  • 讓我們舉個例子。

    usingSystem.Runtime.InteropServices.JavaScript;
    namespaceWASM_Demo;
    publicpartial classProgram
    {
    staticvoidMain(string[] args) { }
    [JSExport]
    publicstaticstringResponse()
    {
    return"""
    <h1>
    Hello World
    </h1>
    """;
    }
    }

    沒關系,但是我們如何在瀏覽器中執行此程式碼?

    執行這個程式的程式碼是dotnet.js的,它內建了wasm-tools,所以沒有必要擔心它。要使用此dotnet.js,我們只需使用一個名為 main.js 的檔。

    import { dotnet } from'./dotnet.js'
    const is_browser = typeof window != "undefined";
    if (!is_browser) thrownewError(`Expected to be running in a browser`);
    const { setModuleImports, getAssemblyExports, getConfig, runMainAndExit } = await dotnet
    .withDiagnosticTracing(false)
    .withApplicationArgumentsFromQuery()
    .create();
    const config = getConfig();
    const exports = awaitgetAssemblyExports(config.mainAssemblyName);
    const html =
    exports
    .WASM_Demo // Namespace
    .Program // class Name
    .Response(); // Function Name
    // Regular javascript code
    document.getElementById("app").innerHTML = `${html}`;
    awaitrunMainAndExit(config.mainAssemblyName, [] /* Console App Args */);




    index.html頁面的樣版已經準備完畢。

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <title>WASM Demo</title>
    <meta charset="UTF-8"/>
    <meta name="viewport"content="width=device-width, initial-scale=1.0"/>
    <link rel="modulepreload"href="./dotnet.js"/>
    </head>
    <body>
    <main id="app"></main>
    <script type="module"src="./main.js"></script>
    </body>
    </html>

    現在,讓我們再看一遍這個過程,

  • HTTP 請求傳入

  • WASM-Tools 處理此問題並行送index.html檔。

  • index.html檔請求dotnet.js和main.js檔,dotnet.js由 WASM-Tools 發送,main.js是我們的自訂程式碼。

  • 透過在 main.js 中使用 dotnet.js,我們可以進入 C# 程式碼中的 Program 類,呼叫 Response 函式並在 main.js 中進行我們想要的任何客戶端更改。

  • 我們還有一件事要做,你需要開啟一個名為 runtimeconfig.template.json 的檔,並將以下 JSON 數據放入其中。

    {
    "wasmHostProperties": {
    "perHostConfig": [
    {
    "name": "browser",
    "html-path": "index.html",
    "Host": "browser"
    }
    ]
    }
    }

    我們已經到了盡頭,程式現在可以執行了。唯一需要的命令是:

    Dotnet run -c Release

    常見問題

    我可以托管所有檔而不是 wasm-tools 嗎?又是如何做到的呢?

    當然,但它可能會變得有點復雜,你用 wasm-tools 制作的計畫不能用於任何其他目的,即控制台應用程式不起作用,wasm-tools 可以工作。因為我們選擇 browser-wasm 作為 RuntimeIdentifier,並且多個 RuntimeIdentifiers 在 .NET 中不可用。作為替代方法,您可以開啟兩個計畫,將第一個計畫設定為 WASM 計畫,然後在第二個計畫中將其設定為控制台應用程式,然後生成第一個計畫並托管輸出資料夾,所有 DLL 和檔都將在那裏。

    這個演示只是索引檔,我可以做多頁嗎?又是如何做到的呢?

    當然,但這比你想象的要難得多,因為這樣做的方法是一種叫做SPA(單頁應用程式)的方法,使用者總是在同一頁面上,只是內容發生了變化。有多種方法可以做到這一點。所以它可以用你的創造力來完成。

    我可以像計數器一樣做動態程式碼嗎?又是如何做到的呢?

    _是的,我也這樣做了,你可以一遍又一遍地呼叫 C# 函式,如果你只是將匯出繫結到 window 物件,你可以從每個 JavaScript 程式碼中呼叫它。