如何使用Razor文件创建普通非组件类并使用RenderFragment简化语法
完全可以实现,你遇到的报错是Blazor Razor编译器的默认行为导致的:所有被识别为组件的.razor文件,无论你是否在@code块外写了顶层标记,编译器都会自动生成BuildRenderTree方法的重写逻辑。默认配置下编译器会把所有.razor文件都当作组件处理,自然会在你继承object时报找不到可重写方法的错误。
有两种可直接落地的实现方案:
方案1(推荐,无多余依赖,生成干净的普通类)
不需要修改Razor文件的写法,只要在.csproj项目文件中给对应Razor文件关闭组件类生成即可:<ItemGroup> <!-- 把路径替换成你自己的razor文件路径 --> <RazorComponent Include="Utils\RazorHelpers.razor" GenerateComponentClass="false" /> </ItemGroup>配置完成后,编译器就不会再强制生成BuildRenderTree重写逻辑,你可以直接按预期写法写代码,不需要写
@inherits object,默认生成的类就是继承object的普通类:@code { // 任意其他业务代码 public RenderFragment Foo => @<span class="foo"></span>; public RenderFragment Render(string? name) => __builder => { // 任意其他逻辑 <text>@name</text>; }; }最终生成的C#代码和你给出的预期代码完全一致,没有多余的组件相关逻辑,也不强制要求项目引用Blazor组件相关的依赖。
方案2(无需修改csproj,取巧兼容编译器逻辑)
如果不想调整项目配置,可以写一个极简的空基类,提供编译器需要的虚方法签名绕开报错:public abstract class RazorTemplateBase { protected virtual void BuildRenderTree(RenderTreeBuilder builder) { // 空实现即可,不需要写逻辑 } }之后在Razor文件顶部指定继承这个基类:
@inherits RazorTemplateBase @code { // 你的代码和之前写法完全一致 public RenderFragment Foo => @<span class="foo"></span>; public RenderFragment Render(string? name) => __builder => { <text>@name</text>; }; }这个方案下因为你没有在@code块外写任何顶层标记,编译器重写的BuildRenderTree方法是空实现,不会产生任何多余渲染逻辑,类也可以当普通类使用,缺点是类会多一个无用的BuildRenderTree方法,且需要引用Microsoft.AspNetCore.Components相关包。
注意:你之前假设"不在@code块外写标记就不会生成BuildRenderTree重写"是旧版MVC Razor的逻辑,Blazor使用的Razor组件编译器目前没有做这个判断,只要走组件生成流程就一定会生成该重写方法。
内容的提问来源于stack exchange,提问作者Miral

