本文分享如何用.NET技术开发“在浏览器端编译和运行C#代码的工具,核心的技术就是用C#编写不依赖于Blazor框架的WebAssembly以及Roslyn技术。
一、 为什么要开发这样的工具?
一些可以在线编写、运行C#代码的网站,实现思路有如下两种:
思路1:把代码从前端提交到在后端服务器上,然后在服务器上进行编译、运行,然后把运行结果再显示到前端。这样做的缺点是无法完成复杂的输入输出、界面交互等。
思路2:用Mono技术编写WebAssembly。这样做的缺点是对于C#语法的跟进不及时,一些新的C#语法不被支持。
思路3:开发一个能在浏览器端编译运行C#代码,并且支持最新C#语法的工具。要开发这样的工具,WebAssembly是一个绕不过去的技术。(本文)
二、 什么是WebAssembly?
传统的前端开发都是使用JavaScript来编写逻辑,而WebAssembly让我们可以用其他编程序言编写在浏览器中运行的程序。由于WebAssembly属于现代浏览器的标准,所以在浏览器中运行WebAssembly程序并不需要安装额外的插件。现在Java、Go、Python等主流的编程语言都已经支持编译为WebAssembly。
三、.NET Blazor WebAssembly的缺点
.NET 中的Blazor WebAssembly技术可以把C#代码编译为WebAssembly运行在浏览器端。但是传统的Blazor WebAssembly是一个侵入性很强的框架,也就是整个系统都必须使用C#技术进行开发,而不能选择只是其中一个组件使用C#代码,其他地方仍然使用传统的JavaScript进行开发。
当然,通过Microsoft.AspNetCore.Components.CustomElements,我们可以只把界面的一小块使用C#进行开发,但是这种方式仍然是“在页面上留一个用C#写的区域”,非常的重量级,而不能实现“只用C#写一个函数”这样轻量级的组件,也就是用C#写一个非侵入性、依赖性很低的轻量级WebAssembly组件。
四、 不用.NET. Blazor WebAssembly,用.NET技术开发WebAssembly
从.NET 6开始,我们可以使用C#编写轻量级的WebAssembly,生成的WebAssembly只需要使用Blazor提供的基础运行环境,而不需要引入整个Blazor WebAssembly技术。
下面,我将会通过一个简单的“用C#计算两个数的和”的例子来演示这个技术的用法。当然,这只是一个简单的演示,实际项目中肯定不会用C#完成这么简单的功能。下面的项目用.NET 7进行演示,其他版本使用可能会略有不同。
step 1 创建一个.NET普通类库项目,named with ClassLibraryWebAssembly
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
step 2.
然后通过Nuget安装如下两个组件:Microsoft.AspNetCore.Components.WebAssembly、Microsoft.AspNetCore.Components.WebAssembly.DevServer
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" />
</ItemGroup>
step 3.,然后把类库项目的csproj文件的根节点中Sdk属性的值修改为"Microsoft.NET.Sdk.BlazorWebAssembly"。
修改后的文件类似如代码 1所示
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" />
</ItemGroup>
</Project>
step 4.在类库项目中创建一个文件Program.cs,内容如代码
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public class Program
{
private static async Task Main(string[] args)
{
}
[JSInvokable]
public static int Add(int i, int j)
{
return i + j;
}
}
}