将 C# 项目编译为 WebAssembly

vcR*_*obe 20 c# webassembly .net-6.0

我需要将 C# 项目编译为 WebAssembly,并能够从 JavaScript 调用一些方法。

我想在需要添加一些新功能的旧 ASP.NET MVC 4 应用程序中使用它,并且我更喜欢使用 C# 而不是 JavaScript/TypeScript。

理想情况下,我想使用 .Net 6 编译为 WebAssembly,但我可以使用任何其他替代方案。

我在 Windows 10 版本 21H1(操作系统内部版本 19043.1415)上运行 .Net 6

我已经安装了:

  • 视觉工作室 2022
  • 工作负载“wasm-tools”(.NET WebAssembly 构建工具)

但每次我搜索有关如何使用 .NET WebAssembly 构建工具的教程、示例等时,结果都是有关 Blazor 的。

我已阅读本教程,但找不到 mono-wasm 编译器(正如我上面所说,我希望尽可能使用 .Net 6 进行编译。)

谁能帮我解决这个问题吗?

谢谢。

S W*_*aye 20

有实验性的 NativeAOT-LLVM ( https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM )。它不是官方的 Microsoft WebAssembly 编译器,由社区支持,但 .Net 6 可用。首先,这仅适用于 Windows,您需要安装并激活 emscripten。我不会在这里介绍安装 emscripten,但您可以阅读https://emscripten.org/docs/getting_started/downloads.html

创建并运行 dotnet c# 库:

  1. 创建库项目:
dotnet new classlib
Run Code Online (Sandbox Code Playgroud)
  1. 创建库代码,我们将使用一些简单的代码来避免编组 JavaScript 字符串等问题,因此在文件中Class1.cs添加
dotnet new classlib
Run Code Online (Sandbox Code Playgroud)

这将创建一个函数,Answer可以从外部托管代码(即从 Javascript)调用

  1. 添加 nuget.config
dotnet new nugetconfig
Run Code Online (Sandbox Code Playgroud)
  1. 在 nuget.config 中添加引用以允许下载实验包。您还可以更改包下载位置,以避免将实验包添加到您的全局 nuget 位置。你的nuget.config应该看起来像:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="globalPackagesFolder" value=".packages" />
  </config>
  <packageSources>
    <!--To inherit the global NuGet package sources remove the <clear/> line below -->
    <clear />
    <add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>
Run Code Online (Sandbox Code Playgroud)
  1. 将编译器的包引用添加到项目的csproj文件中,使其以此结尾:
  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
    <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler.LLVM" Version="7.0.0-*" />
  </ItemGroup>

</Project>
Run Code Online (Sandbox Code Playgroud)
  1. 将您的项目发布到 wasm:
dotnet publish /p:NativeLib=Static /p:SelfContained=true -r browser-wasm -c Debug /p:TargetArchitecture=wasm /p:PlatformTarget=AnyCPU /p:MSBuildEnableWorkloadResolver=false /p:EmccExtraArgs="-s EXPORTED_FUNCTIONS=_Answer%2C_NativeAOT_StaticInitialization -s EXPORTED_RUNTIME_METHODS=cwrap" --self-contained
Run Code Online (Sandbox Code Playgroud)

这将构建引用 browser-wasm 运行时的项目。 MSBuildEnableWorkloadResolver停止构建过程检查 Mono 的 wasm-tools Visual Studio 工作负载,我们在这里没有使用它。(Mono 是一个不同的编译器和运行时,我相信它为 .net 7 提供了类似的支持)。 EmccExtraArgs允许我们向 emscripten 添加参数emcc,并且我们需要导出我们将从 Javascript 调用的两个函数:Answer- 这是我们的库函数,在NativeAOT_StaticInitializationwasm 模块的每个生命周期中调用一次以初始化运行时。请注意名称前面的附加下划线。编译需要一段时间,但完成后您应该有一个子文件夹bin\x64\Debug\net6.0\browser-wasm\native,您可以在其中找到 wasm、一些 html 和一些 javascript。在 html 文件末尾的结束body标记之前,初始化运行时并使用以下命令调用您的函数:

<script>
    Module.onRuntimeInitialized = _ => {
    const corertInit = Module.cwrap('NativeAOT_StaticInitialization', 'number', []);
    corertInit();

    const answer = Module.cwrap('Answer', 'number', []);
    console.log(answer());
    };
</script>
Run Code Online (Sandbox Code Playgroud)

然后将其与您选择的 Web 服务器连接起来,浏览到该页面并检查控制台,如果一切都按计划进行,并且星星对齐(这是实验性的),您应该看到 在此输入图像描述