受欢迎的博客标签

不用Blazor WebAssembly,开发在浏览器端编译和运行WebAssembly C#代码的网站

Published
 

本文分享如何用.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;
        }
    }
}
这里Main方法目前是空的,但是不能被省略。Add方法上的[JSInvokable]表示这个方法可以被JavaScript调用,也就是这个方法属于一个可以被调用的Web Assembly方法。
 
step 5:编译项目,生成文件夹下的wwwroot文件夹中的_framework文件夹中就是生成的Web Assembly和相关文件。
F:\developer_WebAssembly\ClassLibraryWebAssembly\ClassLibrary1\bin\Debug\net7.0\wwwroot\_framework