其实 dotnet 是全栈的首选,原因是因为可以开发的方向太多,比如大本营PC端,以及后台。还有移动端,包括 IOS 和安卓端。现在还能用来写前端,本文就来告诉大家如何在前端使用现有的C#代码,通过 WebAssembly 使用 C# 的代码支持完全静态的网页,也就是不需要任何后台的存在。同时使用 C# 编写的 WebAssembly 可以省去 js 编译时间,同时使用二进制的本地指令,运行效率也有极大的提升。兼顾了开发的友好以及更高的性能

这需要搜 WebAssembly 就可以找到超级多的赞扬的文章,我这里也就不需要多说了。接下来告诉大家使用一个超级简单的代码入门

使用 WebAssmebly 的方式不会影响原有的任何业务,也就是我在已经写了几年的页面里面,可以直接加入 WebAssmembly 的特性,就像多添加一个 js 引用一样。不需要对现有的页面做任何的改动

此时在 C# 里面用的代码都是虚的,不再本文关注的范围内,所以通过 dotnet new console -o YadernawcoLofeleabe创建一个控制台项目

在控制台项目添加一个类,这个类添加静态方法,这个静态方法就是让前端调用的入口方法,给这个字符串添加字符串参数,方便传入

using System;namespace YadernawcoLofeleabe
{class Program{static void Main(string[] args){Console.WriteLine("Hello World!");}}public class Example{public static string Hello(string yourName){return $"Hello {yourName}";}}
}

这里的代码不是重点,大概就是从 Hello 拿到输入,然后修改输入然后输出

接下来就是重点了,如何将 C# 代码编译为 WebAssmebly 了

这里的 C# 需要通过 mono 的辅助用于将 IL 转换为 WebAssembly 的代码,所以需要在Mono官网下载最新的 Mono 的 SDK 安装

点击下载

默认的 Mono 将会安装到 c:\Program Files\Mono\bin\ 文件夹,如果是下载 x86 的就会安装到 c:\Program Files(x86)\Mono\bin\ 文件夹

然后下载 mono 在 wasm 的运行时,请 点击下载 将下载的 zip 文件夹解压缩到本地的文件夹,同时记住这个文件夹,如我将 zip 文件夹解压缩到 f:/lindexi/mono 文件夹

此时准备环境工作就完成了,下一步就是命令行编译了。当然这些步骤都是最基础的步骤,也有封装好的命令,也就是dotnet wasm xx.csproj 完成编译,不过这一步需要先安装工具(注意这个工具还没正式发布)

通过 csc 命令将 C# 代码编译为 IL 文件。打开 VisualStudio 开发者命令行工具,进入到刚才创建的 Program.cs 所在文件夹

csc /target:library -out:Example.dll /noconfig /nostdlib /r:f:/lindexi/mono/wasm-bcl/wasm/mscorlib.dll /r:f:/lindexi/mono/wasm-bcl/wasm/System.dll /r:f:/lindexi/mono/wasm-bcl/wasm/System.Core.dll /r:f:/lindexi/mono/wasm-bcl/wasm/Facades/netstandard.dll /r:f:/lindexi/mono/wasm-bcl/wasm/System.Net.Http.dll /r:f:/lindexi/mono/framework/WebAssembly.Bindings.dll /r:f:/lindexi/mono/framework/WebAssembly.Net.Http.dll Program.cs

注意将 f:/lindexi/mono 文件夹替换为你刚才解压缩的 mono 运行时所在的文件夹

上面的代码通过引用 mono 运行时的库,将 Program.cs 文件编译为 Example.dll 文件

当然这里的 Example.dll 文件现在还是 IL 文件,还需要通过 mono 再次编译为 wasm 文件。注意这里说的编译为 wasm 并不是真的将 IL 编译 wasm 文件,而是编译为运行在 wasm 的 .NET 运行时可解析的文件。上面这句话已经过时,只是我逗比看文档理解不对,其实上面这一步编译的 IL 文件已经可以在 wasm 执行了。原因是在 wasm 会先运行一个 .NET 的运行时,由 .NET 运行时执行这个 IL 文件

单独一个 Example.dll 文件是不能直接运行的,如上面所说,需要添加一个.NET运行时。但是一个 .NET 运行时是超级大的,难道要用户每次打开网页都下载一个这么大的运行时?此时就需要用到 packager.exe 工具,通过这个工具,可以只添加引用的同时支持在 wasm 运行的库

"c:\Program Files\Mono\bin\mono" "f:/lindexi/mono/packager.exe" --copy=always --out=./publish Example.dll

注意上面的路径,如果安装的是 x86 的 mono 那么需要修改路径为 c:\Program Files(x86)\Mono\bin\mono 此外需要将 f:/lindexi/mono/packager.exe 替换为你解压缩的 mono 运行时文件夹

执行上面命令如果看到下面输出,那么就是运行成功

cp: Always - f:\temp\WpfApp1\YadernawcoLofeleabe\Example.dll -> ./publish\managed\Example.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\mscorlib.dll -> ./publish\managed\mscorlib.dll
cp: Always - f:\lindexi\mono\framework\WebAssembly.Bindings.dll -> ./publish\managed\WebAssembly.Bindings.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\Facades\netstandard.dll -> ./publish\managed\netstandard.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.dll -> ./publish\managed\System.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\Mono.Security.dll -> ./publish\managed\Mono.Security.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Xml.dll -> ./publish\managed\System.Xml.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Numerics.dll -> ./publish\managed\System.Numerics.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Core.dll -> ./publish\managed\System.Core.dll
cp: Always - f:\lindexi\mono\framework\WebAssembly.Net.WebSockets.dll -> ./publish\managed\WebAssembly.Net.WebSockets.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\Facades\System.Memory.dll -> ./publish\managed\System.Memory.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Data.dll -> ./publish\managed\System.Data.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Transactions.dll -> ./publish\managed\System.Transactions.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Data.DataSetExtensions.dll -> ./publish\managed\System.Data.DataSetExtensions.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\Facades\System.Drawing.Common.dll -> ./publish\managed\System.Drawing.Common.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.IO.Compression.dll -> ./publish\managed\System.IO.Compression.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.IO.Compression.FileSystem.dll -> ./publish\managed\System.IO.Compression.FileSystem.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.ComponentModel.Composition.dll -> ./publish\managed\System.ComponentModel.Composition.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Net.Http.dll -> ./publish\managed\System.Net.Http.dll
cp: Always - f:\lindexi\mono\framework\WebAssembly.Net.Http.dll -> ./publish\managed\WebAssembly.Net.Http.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Runtime.Serialization.dll -> ./publish\managed\System.Runtime.Serialization.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.ServiceModel.Internals.dll -> ./publish\managed\System.ServiceModel.Internals.dll
cp: Always - f:\lindexi\mono\wasm-bcl\wasm\System.Xml.Linq.dll -> ./publish\managed\System.Xml.Linq.dll

此时打开 Program.cs 所在的文件夹,可以看到文件夹包含了 publish 文件夹,这个文件夹里面的内容就是 wasm 使用的文件了,而刚才编译的 Example.dll 就放在 managed 文件夹里面

下一步就是如何在 html 中使用刚才编译出来的 Excample.dll 文件了,这部分感谢前端的小智的协助

需要在 html 中引用 publish 文件夹下的 mono-config.js 和 runtime.js 和 dotnet.js 文件夹

    <script type="text/javascript" src="./mono-config.js"></script><script type="text/javascript" src="./runtime.js"></script><script async type="text/javascript" src="./dotnet.js"></script>

接下来就是如何在 js 代码调用 C# 编译的 dll 了

通过 Module.mono_bind_static_method 可以将 js 的一个方法绑定到一个静态的方法里面

Module.mono_bind_static_method("[Example] YadernawcoLofeleabe.Example:Hello");

使用格式是 Module.mono_bind_static_method("[dll文件名] 命名空间.类名:静态方法"); 如上面代码

尝试复制下面代码放在 html 里面

        <script type="text/javascript">let that = this;var App = {onClick: function () {that.output.value = "Please wait";that.output.value = that.execute("Ali");},init: function () {that.execute = Module.mono_bind_static_method("[Example] YadernawcoLofeleabe.Example:Hello");that.output = document.getElementById("output");that.button = document.getElementById("button");that.button.disabled = false;}};      </script>

如果你的 dll 命名和命名空间和我不相同,那么请自己修改

接下来就是添加简单的界面了

<!DOCTYPE doctype html>
<html lang="en"><head><!-- Required meta tags --><meta charset="utf-8"><meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport"><!-- Bootstrap CSS --><link crossorigin="anonymous" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/css/bootstrap.min.css" integrity="sha384-SI27wrMjH3ZZ89r4o+fGIJtnzkAnFs3E4qz9DIYioCQ5l9Rd/7UAa8DHcaL8jkWt" rel="stylesheet"><title>Hello, Mono WASM!</title></link></meta></meta></head><body><div class="container"><h1>Hello, world!</h1><form><div class="form-group"><label for="output">Output from C#:</label><textarea class="form-control" id="output" rows="10"></textarea></div><div class="form-group"><button class="btn btn-primary" id="button" onclick="App.onClick" type="button">Run WASM, Run!</button></div></form></div><script type="text/javascript">let that = this;var App = {onClick: function () {that.output.value = "Please wait";that.output.value = that.execute("Ali");},init: function () {that.execute = Module.mono_bind_static_method("[Example] YadernawcoLofeleabe.Example:Hello");that.output = document.getElementById("output");that.button = document.getElementById("button");that.button.disabled = false;}};      document.getElementById("button").addEventListener("click", App.onClick);document.body.addEventListener("load", App.init);</script><script src="./mono-config.js" type="text/javascript"></script><script src="./runtime.js" type="text/javascript"></script><script async="" src="./dotnet.js" type="text/javascript"></script></body>
</html>

尝试开启一个静态的 HTTP 服务器,然后在浏览器访问这个 html 文件,注意将 dll 文件设置用户可下载,这样就完成了。例子可以访问https://0x414c49.github.io/wasm-example/index.html 这里有所有的文件

其实我在入门翻了车,多谢下面大佬的博客,本文大部分代码都是抄下面博客

Run C# natively in the browser through the web assembly via mono-wasm: https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Fitnext.io%2Frun-c-natively-in-the-browser-through-the-web-assembly-via-mono-wasm-60f3d55dd05a

看到这里小伙伴想到了什么?没错,微软 Blazor 就是用这个原理,用 C# 写前端

dotnet 将C#编译为wasm让前端html使用相关推荐

  1. 使用Apache TVM将机器学习编译为WASM和WebGPU

    使用Apache TVM将机器学习编译为WASM和WebGPU TLDR 在Apache TVM深度学习编译器中引入了对WASM和WebGPU的支持.实验表明,在将模型部署到Web时,TVM的WebG ...

  2. DOTNET防止反编译

    DOTNET防止反编译 目录 第一部分 相关理论 一 防止反编译概述 二 DOTNET编译原理简介 三 被反编译的后果 四 保护方案分类 第二部分 实践 一 Net强名称工具SN.EXE 二 使用Do ...

  3. 如何使用LLVM将C语言编译为WASM

    LLVM 在10之后都支持了wasm,但是这是一个实验性的功能,默认是不打开的,另外,在windows上,llvm是不带LLVM静态编译器的,也就是llc,但是Linux倒是自带了llvm的llc,但 ...

  4. 把两个C++项目编译成wasm

    [应用场景说明] C++动态库在不同的平台需要编译成不同的形式,widows下应用时需要编译成dll文件,linux下应用时需要编译成so文件,mac下应用时需要编译成dylib.每升级一次库文件,都 ...

  5. js中立即执行函数会预编译吗_作为前端你了解JavaScript运行机制吗?

    作为前端工程师,大家都知道js是前端一开始就要学会的知识点,js的代码你会写了,那js的运行机制你了解吗?只有了解了js的运行机制,才能在工作中如鱼得水,今天就跟随珠峰的老师一起来了解下js的运行机制 ...

  6. 图解DotNet框架之一:编译与执行引擎(上)

    众所周知,DotNet框架是非常庞大的,光项目创建时的种类就有WPF,WCF,WF这三种最新的技术,还有以前的Web,WinForm,Service,Mobile等等. 这么复杂和庞大的框架,用文字来 ...

  7. node 简繁体转换_编译了wasm版本的OpenCC,在浏览器上直接转换简繁体

    wasm-opencc开放中文转换OpenCC的wasm版本. 这个项目对OpenCC进行了添加修改修改,并利用Emscripten进行编译,在OpenCC进行中文简繁体转换的能力上具有以下特性:可在 ...

  8. 编译原理中的前端和后端

    划分依据:与机器的相关性. 前端工作与源语言有关而与机器无关.后端工作与机器有关. 可以理解为:前端工作把(不同类型的)源语言转换为中间代码,后端工作是将中间代码适用于(不同类型的)机器上.实际应用中 ...

  9. BIM轻量化和Web的应用

           大家好,我是小张同学,一个接触BIM有一段时间的人了,一直混迹在各大论坛学习的潜水党,收获众多.也很感慨与各种前辈们的无私奉献,在此也想分享一点自己一直以来的学习过程.如有理解不足或错误 ...

最新文章

  1. 企业开发与社交开发相辅相成
  2. 推荐:.Net 5开源免费的内容管理系统
  3. 基于Masstransit实现Eventbus的功能
  4. Unity4.3 遮挡剔除:基本知识
  5. nologging mysql_oraclenologgingoperation
  6. 计算机毕业设计springboot家政管理系统
  7. Dlink ?一款交互式FlinkSQL开发平台
  8. python实现网页表单填写_python在网页中自动填充表单
  9. WC-Write Combining 合并写技术
  10. HALO博客配置华为云OSS上传附件
  11. Mac 上 git 命令出现 xcode-select: error: tool ‘xcodebuild‘ requires Xcode, but active developer direc 错误
  12. mysql 集群搭建(Centos7) for Galera
  13. Redis做接口限流
  14. Linux下常用的工具软件
  15. SQL Server 利用WITH AS递归获取层级关系数据
  16. NopCommerce Alipay 支付插件
  17. Mac 定时提醒应用 stretchly 配置
  18. 智能网卡OVS卸载设计
  19. 【slam十四讲第二版】【课本例题代码向】【第七讲~视觉里程计Ⅱ】【使用LK光流(cv)】【高斯牛顿法实现单层光流和多层光流】【实现单层直接法和多层直接法】
  20. Flink教程(31)- Flink网络流控及反压

热门文章

  1. wxGlade的图标,原来是来自蒙德里安的名画!
  2. 《你必须知道的.NET》第1章学习笔记
  3. LuckyDraw app被评为Microsoft365 App Award
  4. diy感应usb摄像头拍照_DIY无线感应充电器
  5. plex 乱码_Plex Media Center现在支持播客
  6. 如何使计算机为您读取文档
  7. vue3.0、cli4项目引入element plus
  8. CodeForces - 1059D(二分+误差)
  9. 感受机房管理化繁为简-新款KVM使用心得
  10. 使用Java API的5个技巧