gpt4 book ai didi

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

转载 作者:我是一只小鸟 更新时间:2023-02-10 06:31:06 28 4
gpt4 key购买 nike

本文中,我将会为大家分享一个如何用.NET技术开发“在浏览器端编译和运行C#代码的工具”,核心的技术就是用C#编写不依赖于Blazor框架的WebAssembly以及Roslyn技术.

1、 为什么要开发这样的工具?

对于编程初学者来讲,开发环境的安装配置是一个令人头疼的事情,如果能让初学者不用做任何的安装配置,直接打开浏览器就能编写、运行代码,那么这将会大大降低编程初学者的学习门槛.

目前已经有一些可以在线编写、运行C#代码的网站了,这些网站的实现思路有如下两种:

思路1 : 把代码从前端提交到在后端服务器上,然后在服务器上进行编译、运行,然后把运行结果再显示到前端。这样做的缺点是无法完成复杂的输入输出、界面交互等.

思路2 : 用Mono技术编写WebAssembly。这样做的缺点是对于C#语法的跟进不及时,一些新的C#语法不被支持.

因此,开发一个能在浏览器端编译运行C#代码,并且支持最新C#语法的工具就很重要了。要开发这样的工具,WebAssembly是一个绕不过去的技术.

2、 什么是WebAssembly ?

传统的前端开发都是使用JavaScript来编写逻辑,而WebAssembly让我们可以用其他编程序言编写在浏览器中运行的程序。由于WebAssembly属于现代浏览器的标准,所以在浏览器中运行WebAssembly程序并不需要安装额外的插件。现在Java、Go、Python等主流的编程语言都已经支持编译为WebAssembly.

3、 Blazor WebAssembly 的缺点 。

 .NET 中的Blazor WebAssembly技术可以把C#代码编译为WebAssembly运行在浏览器端。但是传统的Blazor WebAssembly是一个侵入性很强的框架,也就是整个系统都必须使用C#技术进行开发,而不能选择只是其中一个组件使用C#代码,其他地方仍然使用传统的JavaScript进行开发。当然,通过Microsoft.AspNetCore.Components.CustomElements,我们可以只把界面的一小块使用C#进行开发,但是这种方式仍然是“在页面上留一个用C#写的区域”,非常的重量级,而不能实现“只用C#写一个函数”这样轻量级的组件,也就是用C#写一个非侵入性、依赖性很低的轻量级WebAssembly组件.

4、 不用Blazor WebAssembly ,用.NET 技术开发WebAssembly 。

从.NET 6开始,我们可以使用C#编写轻量级的WebAssembly,生成的WebAssembly只需要使用Blazor提供的基础运行环境,而不需要引入整个Blazor WebAssembly技术.

                下面,我将会通过一个简单的“用C#计算两个数的和”的例子来演示这个技术的用法。当然,这只是一个简单的演示,实际项目中肯定不会用C#完成这么简单的功能。下面的项目用.NET 7进行演示,其他版本使用可能会略有不同.

1、 创建一个.NET普通类库项目,然后通过Nuget安装如下两个组件:Microsoft.AspNetCore.Components.WebAssembly、Microsoft.AspNetCore.Components.WebAssembly.DevServer,然后把类库项目的csproj文件的根节点中Sdk属性的值修改为"Microsoft.NET.Sdk.BlazorWebAssembly".

修改后的文件类似如 代码 1 所示.

  。

代码 1  csproj项目文件 。

                          
                            <
                          
                          
                            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
                          
                          
                            >
                          
                        

  。

2、 在类库项目中创建一个文件Program.cs,内容如代码 2所示.

  。

代码 2 Program.cs 。

                          
                            using
                          
                          
                             Microsoft.JSInterop;


                          
                          
                            namespace
                          
                          
                             Demo1
{
    
                          
                          
                            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方法.

3、 编译项目,生成文件夹下的wwwroot文件夹中的_framework文件夹中就是生成的Web Assembly和相关文件.

4、 用任何你喜欢的前端技术创建一个前端项目。我这里不使用任何的前端框架,而是直接用普通的HTML+Javascript来编写前端项目.

首先,我们要把上一步生成的_framework文件夹复制到前端项目的根文件夹下.

然后,我们编写index.html文件,内容如代码 3所示.

代码 3 index.html 。

                          
                            <
                          
                          
                            html 
                          
                          
                            lang
                          
                          
                            ="en"
                          
                          
                            >
                          
                          
                            <
                          
                          
                            head
                          
                          
                            >
                          
                          
                            <
                          
                          
                            meta 
                          
                          
                            charset
                          
                          
                            ="UTF-8"
                          
                          
                            />
                          
                          
                            </
                          
                          
                            head
                          
                          
                            >
                          
                          
                            <
                          
                          
                            body
                          
                          
                            ></
                          
                          
                            body
                          
                          
                            >
                          
                          
                            <
                          
                          
                            script 
                          
                          
                            src
                          
                          
                            ="_framework/blazor.webassembly.js"
                          
                          
                             autostart
                          
                          
                            ="false"
                          
                          
                            ></
                          
                          
                            script
                          
                          
                            >
                          
                          
                            <
                          
                          
                            script
                          
                          
                            >
                          
                          
                                
        window.onload 
                          
                          
                            =
                          
                          
                             async 
                          
                          
                            function
                          
                          
                             () {
            await Blazor.start();
            const r 
                          
                          
                            =
                          
                          
                             await DotNet.invokeMethodAsync(
                
                          
                          
                            '
                          
                          
                            Demo1
                          
                          
                            '
                          
                          
                            ,
                          
                          
                            //
                          
                          
                            程序集的名字
                          
                          
                            '
                          
                          
                            Add
                          
                          
                            '
                          
                          
                            ,
                          
                          
                            //
                          
                          
                            要调用的标注了[JSInvokable]方法的名字
                          
                          
                            666
                          
                          
                            ,
                          
                          
                            //
                          
                          
                            若干参数
                          
                          
                            333
                          
                          
                            
            );
            alert(r);
        };    
    
                          
                          
                            </
                          
                          
                            script
                          
                          
                            >
                          
                          
                            </
                          
                          
                            html
                          
                          
                            >
                          
                        

  。

                接下来解释一下上面的代码,<script src="_framework/blazor.webassembly.js" autostart="false"></script>用来引入相关的文件。Blazor.start();用来启动Blazor运行时环境; DotNet.invokeMethodAsync用来调用WebAssembly中的方法,第一个参数为被调用的程序集的名字,第二个参数为被调用的方法的名字,之后的参数为给被调用的方法传递的参数值.

                可以看到,这里我们就是把WebAssembly当成一个组件在用,完全不对页面有其他特殊的要求。所以这个组件可以在任何前端框架中使用,也可以和其他前端的库一起使用.

                最后,我们运行这个前端项目. 由于Blazor会生成blat、dll等不被Web服务器默认接受的文件类型,所以请确保在Web服务器上为如下格式的文件配置MimeType:.pdb、.blat、.dat、.dll、.json、.wasm、.woff、.woff2。我这里测试用的Web服务器是IIS,所以在网站根文件夹下创建如所示的Web.config文件即可,如代码 4所示,使用其他Web服务器的开发者请参考所使用的Web服务器的手册进行MimeType的配置.

代码 4 Web.config 。

                          
                            <?
                          
                          
                            xml version="1.0" encoding="UTF-8"
                          
                          
                            ?>
                          
                          
                            <
                          
                          
                            configuration
                          
                          
                            >
                          
                          
                            <
                          
                          
                            system.webServer
                          
                          
                            >
                          
                          
                            <
                          
                          
                            staticContent
                          
                          
                            >
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".pdb"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".blat"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".dat"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".dll"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".json"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".wasm"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".woff"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            remove 
                          
                          
                            fileExtension
                          
                          
                            =".woff2"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".pdb"
                          
                          
                             mimeType
                          
                          
                            ="application/octet-stream"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".blat"
                          
                          
                             mimeType
                          
                          
                            ="application/octet-stream"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".dll"
                          
                          
                             mimeType
                          
                          
                            ="application/octet-stream"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".dat"
                          
                          
                             mimeType
                          
                          
                            ="application/octet-stream"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".json"
                          
                          
                             mimeType
                          
                          
                            ="application/json"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".wasm"
                          
                          
                             mimeType
                          
                          
                            ="application/wasm"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".woff"
                          
                          
                             mimeType
                          
                          
                            ="application/font-woff"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            mimeMap 
                          
                          
                            fileExtension
                          
                          
                            =".woff2"
                          
                          
                             mimeType
                          
                          
                            ="application/font-woff"
                          
                          
                            />
                          
                          
                            </
                          
                          
                            staticContent
                          
                          
                            >
                          
                          
                            </
                          
                          
                            system.webServer
                          
                          
                            >
                          
                          
                            </
                          
                          
                            configuration
                          
                          
                            >
                          
                        

5、 在浏览器端访问Web服务器中的index.html,如果看到如Figure 1所示的弹窗,就说明Javascript成功了调用了C#编写的Add方法.

  。

Figure 1 程序执行弹窗 。

5、 C# 编写WebAssembly 的应用场景 。

C#编写的WebAssembly默认占的流量比较大,大约要占到30MB。我们可以通过BlazorLazyLoad、启用Brotli算法等方式把流量降到5MB以下,具体用法请网上搜索相关资料.

在我看来,用C#编写WebAssembly有包含但不限于如下的场景.

场景1 、 复用一些.NET组件或者C#代码。这些已经存在的.NET组件或者C#代码虽然也能用Javascript重写,但是这样增加了额外的工作量。而通过WebAssembly就可以直接重用这些组件。比如,我曾经在后端开发用到过一个PE文件解析的Nuget包,这个包采用的.NET Standard标准开发,而且全部是在内存中进行文件内容的处理,因此我就可以直接在WebAssembly中继续使用这个包在前端对PE文件进行处理.

场景2 、 使用一些WebAssembly组件。因为C/C++等语言编写的程序可以移植为WebAssembly版本,因此很多经典的C/C++开发的软件也可以继续在前端使用。比如音视频处理的ffmpeg已经有了WebAssembly版本,因此我们就可以用C#调用它进行音视频的处理;再比如,著名的计算机视觉库OpenCV也被移植到了WebAssembly中,因此我们也可以使用C#在前端进行图像识别、图像处理等操作。WebAssembly非常适合开发“在线图像处理、在线音视频、在线游戏”等工具类应用的开发.

场景3 、 开发一些复杂度高的前端组件。我们知道,在开发复杂度高的项目的时候,Javascript经常是力不从心,即使是Typescript也并不会比Javascript有更根本性的改善。相比起来,C#等更适合工程化的开发,因此一些复杂度非常高的前端组件用C#编写为WebAssembly有可能更合适.

上面提到的这些场景下,我们可以只把部分组件用C#开发为WebAssembly,其他部分以及项目整体仍然可以继续用Javascript进行开发,这样各个语言可以发挥各自的特色.

6、 C# 回调JavaScript 中的方法 。

在编写WebAssembly的时候,我们可能需要在C#中调用Javascript中的方法。我们可以通过IJSRuntime、IJSInProcessRuntime分别调用Javascript中的异步方法和同步方法.

再创建一个类库项目Demo2,首先按照上面第四节中对项目进行配置,不再赘述.

index.html和Program.cs的代码如代码 5和代码 6所示.

代码 5 index.html 。

                          
                            <
                          
                          
                            html 
                          
                          
                            lang
                          
                          
                            ="en"
                          
                          
                            >
                          
                          
                            <
                          
                          
                            head
                          
                          
                            >
                          
                          
                            <
                          
                          
                            meta 
                          
                          
                            charset
                          
                          
                            ="UTF-8"
                          
                          
                            />
                          
                          
                            </
                          
                          
                            head
                          
                          
                            >
                          
                          
                            <
                          
                          
                            body
                          
                          
                            >
                          
                          
                            <
                          
                          
                            div 
                          
                          
                            id
                          
                          
                            ="divDialog"
                          
                          
                             style
                          
                          
                            ="display:none"
                          
                          
                            >
                          
                          
                            <
                          
                          
                            div 
                          
                          
                            id
                          
                          
                            ="divMsg"
                          
                          
                            ></
                          
                          
                            div
                          
                          
                            >
                          
                          
                            <
                          
                          
                            input 
                          
                          
                            type
                          
                          
                            ="text"
                          
                          
                             id
                          
                          
                            ="txtValue"
                          
                          
                            />
                          
                          
                            <
                          
                          
                            button 
                          
                          
                            id
                          
                          
                            ="btnClose"
                          
                          
                            >
                          
                          close
                          
                            </
                          
                          
                            button
                          
                          
                            >
                          
                          
                            </
                          
                          
                            div
                          
                          
                            >
                          
                          
                            <
                          
                          
                            ul 
                          
                          
                            id
                          
                          
                            ="ulMsgs"
                          
                          
                            >
                          
                          
                            </
                          
                          
                            ul
                          
                          
                            >
                          
                          
                            </
                          
                          
                            body
                          
                          
                            >
                          
                          
                            <
                          
                          
                            script 
                          
                          
                            src
                          
                          
                            ="_framework/blazor.webassembly.js"
                          
                          
                             autostart
                          
                          
                            ="false"
                          
                          
                            ></
                          
                          
                            script
                          
                          
                            >
                          
                          
                            <
                          
                          
                            script
                          
                          
                            >
                          
                          
                            function
                          
                          
                             showMessage(msg) {
        const divDialog 
                          
                          
                            =
                          
                          
                             document.getElementById(
                          
                          
                            "
                          
                          
                            divDialog
                          
                          
                            "
                          
                          
                            );
        divDialog.style.display 
                          
                          
                            =
                          
                          
                            "
                          
                          
                            block
                          
                          
                            "
                          
                          
                            ;
        const divMsg 
                          
                          
                            =
                          
                          
                             document.getElementById(
                          
                          
                            "
                          
                          
                            divMsg
                          
                          
                            "
                          
                          
                            );
        divMsg.innerHTML 
                          
                          
                            =
                          
                          
                             msg;
        const txtValue 
                          
                          
                            =
                          
                          
                             document.getElementById(
                          
                          
                            "
                          
                          
                            txtValue
                          
                          
                            "
                          
                          
                            );
        const btnClose 
                          
                          
                            =
                          
                          
                             document.getElementById(
                          
                          
                            "
                          
                          
                            btnClose
                          
                          
                            "
                          
                          
                            );
        
                          
                          
                            return
                          
                          
                            new
                          
                          
                             Promise(resolve 
                          
                          
                            =>
                          
                          
                             {            
            btnClose.onclick 
                          
                          
                            =
                          
                          
                            function
                          
                          
                             () {
                divDialog.style.display 
                          
                          
                            =
                          
                          
                            "
                          
                          
                            none
                          
                          
                            "
                          
                          
                            ;
                resolve(txtValue.value);
            };
        });
    }
    
                          
                          
                            function
                          
                          
                             appendMessage(msg) {
        const li 
                          
                          
                            =
                          
                          
                             document.createElement(
                          
                          
                            "
                          
                          
                            li
                          
                          
                            "
                          
                          
                            );
        li.innerHTML 
                          
                          
                            =
                          
                          
                             msg;
        const ulMsgs 
                          
                          
                            =
                          
                          
                             document.getElementById(
                          
                          
                            "
                          
                          
                            ulMsgs
                          
                          
                            "
                          
                          
                            );
        ulMsgs.appendChild(li);
    }
    window.onload 
                          
                          
                            =
                          
                          
                             async 
                          
                          
                            function
                          
                          
                             () {
        await Blazor.start();
        await DotNet.invokeMethodAsync(
                          
                          
                            '
                          
                          
                            Demo2
                          
                          
                            '
                          
                          
                            ,
                          
                          
                            '
                          
                          
                            Count
                          
                          
                            '
                          
                          
                            );
    };

                          
                          
                            </
                          
                          
                            script
                          
                          
                            >
                          
                          
                            </
                          
                          
                            html
                          
                          
                            >
                          
                        

  。

代码 6 Program.cs 。

                          
                            using
                          
                          
                             Microsoft.AspNetCore.Components.WebAssembly.Hosting;

                          
                          
                            using
                          
                          
                             Microsoft.JSInterop;


                          
                          
                            namespace
                          
                          
                             Demo2;


                          
                          
                            public
                          
                          
                            class
                          
                          
                             Program
{
    
                          
                          
                            private
                          
                          
                            static
                          
                          
                             IJSRuntime js;

    
                          
                          
                            private
                          
                          
                            static
                          
                          
                            async
                          
                           Task Main(
                          
                            string
                          
                          
                            [] args)
    {
        
                          
                          
                            var
                          
                           builder =
                          
                             WebAssemblyHostBuilder.CreateDefault(args);
        
                          
                          
                            var
                          
                           host =
                          
                             builder.Build();
        js 
                          
                          = host.Services.GetRequiredService<IJSRuntime>
                          
                            ();
        
                          
                          
                            await
                          
                          
                             host.RunAsync();
    }

    [JSInvokable]
    
                          
                          
                            public
                          
                          
                            static
                          
                          
                            async
                          
                          
                             Task Count()
    {
        
                          
                          
                            string
                          
                           strCount = 
                          
                            await
                          
                           js.InvokeAsync<
                          
                            string
                          
                          >(
                          
                            "
                          
                          
                            showMessage
                          
                          
                            "
                          
                          ,
                          
                            "
                          
                          
                            Input Count
                          
                          
                            "
                          
                          
                            );
        
                          
                          
                            for
                          
                          (
                          
                            int
                          
                           i=
                          
                            0
                          
                          ;i<
                          
                            int
                          
                          .Parse(strCount);i++
                          
                            )
        {
            ((IJSInProcessRuntime)js).InvokeVoid(
                          
                          
                            "
                          
                          
                            appendMessage
                          
                          
                            "
                          
                          
                            ,i);
        }
        ((IJSInProcessRuntime)js).InvokeVoid(
                          
                          
                            "
                          
                          
                            alert
                          
                          
                            "
                          
                          , 
                          
                            "
                          
                          
                            Done
                          
                          
                            "
                          
                          
                            );
    }
}
                          
                        

       Index.html中定义的appendMessage方法是一个同步方法,用于把给定的消息附加到ul中;showMessage是一个异步方法,用于显示一个用html模拟的输入对话框,当用户点击【Close】按钮以后关闭对话框,并且返回用户输入的内容,这个操作涉及Javascript中的Promise相关概念,对这个不了解的请查看相关资料.

                Program.cs中,在Main方法中获取用于调用Javascript代码的IJSRuntime服务。IJSRuntime接口中提供了InvokeAsync、InvokeVoidAsync两个方法,分别用于异步地调用JavaScript中的有返回值和无返回值的方法。如果想同步地调用Javascript中的方法,则需要把IJSRuntime类型的对象转型为IJSInProcessRuntime类型,然后调用它的InvokeVoid、Invoke方法。标注了[JSInvokable]的Count()方法是异步方法,在Javascript中调用C#中的异步方法的方式是一样的.

7、 运行时编译C# 代码:Roslyn 。

.NET中的Roslyn用于在运行时编译C#代码,Roslyn支持在WebAssembly中使用,所以我们这里就用这个组件来完成C#代码的编译。Roslyn的用法在网上的资料很多,我这里不再详细讲解.

唯一需要注意的就是:Roslyn编译的默认是并行编译的,因为这样可以提高编译速度。但是受限于浏览器沙盒环境的限制,WebAssembly不支持并行操作,因此如果用默认的Roslyn编译设置,在执行编译操作的时候,Roslyn会抛出“System.PlatformNotSupportedException: Cannot wait on monitors on this runtime”这个错误信息。因此,需要在CSharpCompilationOptions中设置concurrentBuild=false,如代码 7所示.

代码 7 关闭concurrentBuild 。

                          
                            var
                          
                           compilationOptions = 
                          
                            new
                          
                           CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, concurrentBuild: 
                          
                            false
                          
                          
                            );

                          
                          
                            var
                          
                           scriptCompilation =
                          
                             CSharpCompilation.CreateScriptCompilation(
                          
                          
                            "
                          
                          
                            main.dll
                          
                          
                            "
                          
                          , syntaxTree, options: compilationOptions).AddReferences(references);
                        

  。

8、 替换默认Console 类的实现 。

由于浏览器运行环境的限制,并不是所有.NET类都可以调用的,或者其功能是受限的。比如WebAssembly中调用IO类的时候,并不能随意的读写用户磁盘上的文件,只能受限于浏览器沙盒环境的安全限制。再比如WebAssembly中可以调用HttpClient类发出Http请求,但是同样受浏览器的跨域访问的限制。WebAssembly很强大,但是再强大也跳不出浏览器的限制.

在这个在线编译、运行C#代码的工具中,我希望用户可以使用Console.WriteLine()、Console.ReadLine()来和用户进行输出和输入的交互。然而,在Web Assembly中,Console.WriteLine()是在开发人员工具的控制台中输出,相当于执行JavaScript中的console.log();在Web Assembly中,Console.ReadLine()无法使用。因此,我编写了一个同名的Console类,并且提供了WriteLine()、ReadLine()方法的实现,把它们分别用JavaScript中的alert()、prompt()两个函数来实现。在使用Roslyn编译用户编写的代码的时候,使用我这个自定义的Console类的程序集来代替System.Console.dll,这样用户编写的代码中的Console类就调用我自定义的类了.

9、 项目的演示和代码地址 。

我把这个项目部署到了互联网上,大家可以访问 https://block.youzack.com/editor.html 来使用它。效果如Figure 2所示.

  。

Figure 2运行效果 。

在代码编辑器中编写C#代码,然后点击【Run】按钮就可以看到代码的编译、运行效果。如果代码有编译问题,界面也会显示出来详细的编译错误信息.

项目的开源地址为: https://github.com/yangzhongke/WebCSC 。

10、 总结 。

自从.NET 6开始,我们可以脱离传统的侵入性强的Blazor WebAssembly框架,从而使用C#编写轻量级、无侵入的WebAssembly程序,从而和Javascript一起协同开发,让项目在开发效率、工程化管理等方面取得更好的效果.

本文介绍了用C#开发无侵入的WebAssembly组件,而且分享了一个在浏览器端编写、编译和运行C#开发的开源项目.

最后此篇关于不用BlazorWebAssembly,开发在浏览器端编译和运行C#代码的网站的文章就讲到这里了,如果你想了解更多关于不用BlazorWebAssembly,开发在浏览器端编译和运行C#代码的网站的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com