您是否也有想在浏览器中实时的编辑代码并且渲染的想法?

是否,浏览器,实时,编辑,代码,并且,渲染,想法 · 浏览次数 : 223

小编点评

由于WebAssembly不支持多线程,无法使用C#的异步方法进行多线程的编译。因此,无法使用C#动态编译Blazor组件库。

正文

不知道是否有人跟我一样想在浏览器上直接可以动态的编译blazor的一些组件库?而不是通过引用NuGet以后才能查看到效果,并且在使用别人的组件的时候可以在动态的调整组件的一些样式

不说了开始正文:

本文我们将使用Masa提供的一个组件实现动态编译github.com直通车 ,执行环境将在WebAssembly中执行,为什么使用WebAssembly而不是Server呢?首先我们需要先了解这俩种模式的执行原理

WebAssembly:

  • Blazor WebAssemblyBlazor WebAssembly,用于使用 .NET 生成交互式客户端 Web 应用。 Blazor WebAssembly 使用无插件或将代码重新编译为其他语言的开放式 Web 标准。 Blazor WebAssembly 适用于所有新式 Web 浏览器,包括移动浏览器。

Server:

  • Blazor ServerASP.NET Core 应用中支持在服务器上托管 Razor 组件。 可通过 SignalR 连接处理 UI 更新。

    运行时停留在服务器上并处理:

    • 执行应用的 C# 代码。
    • 将 UI 事件从浏览器发送到服务器。
    • 将 UI 更新应用于服务器发送回的已呈现的组件。

由于编译是完全可操作的,存在安全问题,在Server的模式下用户编译的环境就是服务器的环境,这样用户就可以通过动态编译代码实现操作侵入安全,问题很严重,如果有心人使用对于安全影响过于严重,不建议在Server中使用动态编译

实现我们来创建一个空的WebAssembly项目

mkdir compileRazor
cd compileRazor
dotnet new blazorwasm-empty

使用vs打开项目添加Masa.Blazor.Extensions.Languages.Razor ,将一下代码添加到项目文件中

    <PackageReference Include="Masa.Blazor.Extensions.Languages.Razor" Version="0.0.1" />

修改Program.cs文件的代码

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using compileRazor;
using Masa.Blazor.Extensions.Languages.Razor;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

var app = builder.Build();

// 初始化RazorCompile
RazorCompile.Initialized(await GetReference(app.Services), await GetRazorExtension());

await app.RunAsync();

// 添加程序集引用
async Task<List<PortableExecutableReference>?> GetReference(IServiceProvider services)
{
    #region WebAsembly

    // need to add Service
    var httpClient = services.GetService<HttpClient>();

    var portableExecutableReferences = new List<PortableExecutableReference>();
    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        try
        {
            //你需要通过网络获取程序集,应为无法通过程序集目录获取
            var stream = await httpClient!.GetStreamAsync($"_framework/{assembly.GetName().Name}.dll");
            if (stream.Length > 0)
            {
                portableExecutableReferences?.Add(MetadataReference.CreateFromStream(stream));
            }
        }
        catch (Exception e) // There may be a 404
        {
            Console.WriteLine(e.Message);
        }
    }

    #endregion

    // 由于WebAssembly和Server返回portableexecutablerreference机制不同,需要分开处理
    return portableExecutableReferences;
}

async Task<List<RazorExtension>> GetRazorExtension()
{
    var razorExtension = new List<RazorExtension>();

    foreach (var asm in typeof(Program).Assembly.GetReferencedAssemblies())
    {
        razorExtension.Add(new AssemblyExtension(asm.FullName, AppDomain.CurrentDomain.Load(asm.FullName)));
    }

    return razorExtension;
}

修改Pages\Index.razor的代码


@page "/"
@using Masa.Blazor.Extensions.Languages.Razor;

<button class="button" @onclick="Run">刷新</button>

<div class="input-container">
    <textarea @bind="Code" type="text" class="input-box" placeholder="请输入执行代码" >
    </textarea>
</div>

@if (ComponentType != null)
{
    <DynamicComponent Type="ComponentType"></DynamicComponent>
}

@code{

    private string Code = @"<body>
    <div id='app'>
        <header>
            <h1>Doctor Who&trade; Episode Database</h1>
        </header>

        <nav>
            <a href='main-list'>Main Episode List</a>
            <a href='search'>Search</a>
            <a href='new'>Add Episode</a>
        </nav>

        <h2>Episodes</h2>

        <ul>
            <li>...</li>
            <li>...</li>
            <li>...</li>
        </ul>

        <footer>
            Doctor Who is a registered trademark of the BBC. 
            https://www.doctorwho.tv/
        </footer>
    </div>
</body>";

    private Type? ComponentType;

    private void Run()
    {
        ComponentType = RazorCompile.CompileToType(new CompileRazorOptions()
        {
            Code = Code // TODO: 在WebAssembly下保证ConcurrentBuild是false 因为Webassembly不支持多线程
        });
        StateHasChanged();
    }

}

<style>
    .button{
        width: 100%;
        font-size: 22px;
        background-color: cornflowerblue;
        border: 0px;
        margin: 5px;
        border-radius: 5px;
        height: 40px;
    }
    .input-container {
        width: 500px;
        margin: 0 auto;
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 5px;
    } 
    .input-box {
        width: 100%;
        height: 100px;
        border: 1px solid #ccc;
        border-radius: 5px;
        font-size: 14px;
    }
</style>

然后启动程序效果如图:

首次编译会比较慢,在WebAssembly下还可以因为电脑问题造成卡顿,如果是需要提供开发效率可以使用Server调试,在Server调试的话是比WebAssembly快很多,而且WebAssembly还没有做Aot,性能不会太好

来自token的分享

技术交流群:737776595

推荐一个超级好用的Blazor UI组件 MASA Blazor 开源协议 MIT 商用完全没问题

与您是否也有想在浏览器中实时的编辑代码并且渲染的想法?相似的内容:

您是否也有想在浏览器中实时的编辑代码并且渲染的想法?

不知道是否有人跟我一样想在浏览器上直接可以动态的编译blazor的一些组件库?而不是通过引用NuGet以后才能查看到效果,并且在使用别人的组件的时候可以在动态的调整组件的一些样式 不说了开始正文: 本文我们将使用Masa提供的一个组件实现动态编译github.com直通车 ,执行环境将在WebAss

Blazor如何实现类似于微信的Tab切换?

是否有小伙伴在使用tab的时候想进行滑动切换Tab? 并且有滑动左出左进,右出右进的效果 ,本文将讲解怎么在Blazor中去通过滑动切换Tab 本文中的UI组件使用的是MASA Blazor,您也可以是其他的UI框架,这个并不影响实际的运行效果,本文案例是兼容PC和Android的,演示效果是and

C#中关于 object,dynamic 一点使用心得

首先说一下使用场景 WebAPI接口入参使用 object和 dynamic 后续解析和处理 1.object和dynamic 区别 在.NET中,object和dynamic也有一些区别: object:object是.NET中的顶级类,所有类都是object的子类。在C#中,您可以使用objec

开源API越权漏洞检测系统推荐:IDOR_detect_tool

相信大部分读者跟我一样,每天都在写各种API为Web应用提供数据支持,那么您是否有想过您的API是否足够安全呢? Web应用的安全是网络安全中不可忽视的关键方面。我们必须确保其Web应用与后台通信的安全,以防止数据泄露,因为这可能导致重大的财务损失和声誉受损。 而在Web应用的安全问题中,最常见的漏

给公众号接入`FastWiki`智能AI知识库,让您的公众号加入智能行列

最近由于公众号用户太多,我就在思考有啥方式能给微信公众号的粉丝提供更多的更好的服务?这个时候我就想是否可以给公众号接入一下AI?让用户跟微信公众号对话,然后还能回到用户的问题,并且我提供一些资料让AI帮我回复用户的信息? 这个时候刚刚好我们的FastWiki项目满足了部分需求,然后我们就顺便加入了微

《最新出炉》系列入门篇-Python+Playwright自动化测试-10-标签页操作(tab)

1.简介 标签操作其实也是基于浏览器上下文(BrowserContext)进行操作的,而且宏哥在之前的BrowserContext也有提到过,但是有的童鞋或者小伙伴还是不清楚怎么操作,或者思路有点模糊,因此今天单独来对其进行讲解和分享一下,希望您有所帮助。 2.单标签页 单个标签操作这个是最简单的,

Docker简介

Docker简介 1、是什么 问题:为什么会有docker出现 假定你在开发一个网络商城,您使用的是一台笔记本电脑而且您的开发环境具有特定的配置。其他开发人员身处的环境配置也各有不同。您正在开发的应用依赖于您当前的配置且还要依赖于某些配置文件。此外,您的企业还拥有标准化的测试和生产环境境,且具有自身

个人团队兼职开发app(社交,语聊1v1,视频直播)

如果您有意向创业,意向社交类产品,如语聊,及时通信,视频直播,1v1等,又苦无没有人力资源。 我们岁数都是30+,在互联网行业摸爬滚打十年有余。 后端,前端,客户端,运维,四个人。 我们共事很长一段时间。 所有技术,三方,运营后台,产品后台都可以跟您进行沟通。 一些偏运营,产品思维的,我们也可以拉几

[转帖]Redis 运维实战 第09期:Redis 规范

https://cloud.tencent.com/developer/article/1986835 这是专栏《Redis 运维实战》的最后一篇,感谢您的阅读。也感谢 9 篇文章的审稿人:无为,提出了多个修改建议,让文章内容更全面。 由于能力有限,系列文章难免会存在错误或者遗漏,如果您有任何建议,

刺激!ChatGPT给我虚构了一本书?

ChatGPT很强大,可以帮我们处理很多问题,但这些问题的答案的正确性您是否有考证过呢? 昨晚,DD就收到了一个有趣的反馈: 提问:有什么关于数据权限设计的资料推荐吗? ChatGPT居然介绍了一本根本不存在的书《数据权限设计与实现》,作者居然还是我... 那么你在使用ChatGPT的时候,有碰到过