• 再学Blazor——扩展方法


    上篇提到 Blazor 组件的高级写法,是采用扩展方法对 HTML 元素和组件进行扩展,以便于书写组件结构和代码阅读。本篇主要介绍扩展方法实现的思路。

    • 什么是扩展方法
    • 要扩展哪个类
    • 扩展方法的实现

    1. 什么是扩展方法

    若要对一个 C# 类型添加新方法,一是修改源码,二是派生类,三是扩展方法。前两者不是万能的,第一种我们不一定有源码,第二种类型不一定能继承,只有第三种是万能的方法,在项目中新建一个扩展类型即可对任何类型进行扩展。

    一个扩展方法需要有如下条件:

    • 添加扩展类,类必须声明 static 修饰符
    • 添加方法,方法必须声明 static 修饰符
    • 方法第一个参数必须是扩展类型,且要有 this 关键字
    //扩展类型
    static class Extension
    {
    static void SayHello (this string name)
    {
    Console.WriteLine($"Hello, I'm {name}.");
    }
    }
    //测试
    var name = "Known";
    name.SayHello();
    //输出
    Hello, I'm Known.

    2. 要扩展哪个类

    上篇提到组件的高级写法,需要覆写组件的 BuildRenderTree 方法,这个方法有唯一类型参数 RenderTreeBuilder,对,就是这个类型,我们从它开始扩展一切 HTML 基本元素及自定义组件。

    下面看看 RenderTreeBuilder 有哪些原生方法。

    • OpenElement,打开一个元素,呈现
      等开始标签
    • CloseElement,关闭一个元素,呈现
    等关闭标签
  • OpenComponent,打开一个组件,呈现
  • CloseComponent,关闭一个组件,呈现
  • AddAttribute,添加元素和组件的属性,有8个重载方法
  • AddMultipleAttributes,一次性添加多个属性,参数为字典类型
  • AddContent,添加标签内部的内容,有6个重载方法
  • AddMarkupContent,添加原始 HTML 字符内容
  • AddElementReferenceCapture,添加元素对象参考,通过它可获取元素对象的实例
  • AddComponentReferenceCapture,添加组件对象参考,通过它可获取组件对象的实例

掌握以上这些方法的使用后,我们就可以开发扩展我们需要的元素和组件。

3. 扩展方法的实现

由于 HTML 元素标签及其属性众多,为了方便且全面适配所有属性,增加一个属性建造者类型 AttributeBuilder 来管理元素属性。建造者类型如下:

public class AttributeBuilder
{
private readonly RenderTreeBuilder builder;
public AttributeBuilder(RenderTreeBuilder builder)
{
this.builder = builder;
}
public AttributeBuilder Add(string name, object value)
{
if (value != null)
builder.AddAttribute(1, name, value);
return this;
}
public AttributeBuilder Id(string id) => Add("id", id);
public AttributeBuilder Name(string name) => Add("name", name);
...
}

添加一个 HTML 元素扩展类,用于扩展 HTML 元素,代码示例如下:

public static class HtmlExtension
{
//通用元素扩展方法
public static void Element(this RenderTreeBuilder builder, string name, Action child = null)
{
builder.OpenElement(0, name);
var attr = new AttributeBuilder(builder);
child?.Invoke(attr);
builder.CloseElement();
}
//div标签
public static void Div(this RenderTreeBuilder builder, Action child) => builder.Element("div", child);
...
}

下面写一个元素扩展方法的示例,并将呈现的 HTML 结构与 C# 代码进行比对,直观感受一下高级写法的妙处。

protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.Div(attr => //
{ //
attr.Id("myPanel").Class("panel"); //
builder.Div(attr => //
{ //
attr.Class("header"); //
//这里构造 Panel 头部内容 //
}); //
builder.Div(attr => //
{ //
attr.Class("body"); //
//这里构造 Panel 身体内容 //
}); //
}); //
}

再次优化一下扩展方法的示例,下面代码看起来是不是更整齐了一些。

protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.Div("myPanel", "panel", attr => //
{ //
builder.Div("header", attr => //
{ //
//这里构造 Panel 头部内容 //
}); //
builder.Div("body", attr => //
{ //
//这里构造 Panel 身体内容 //
}); //
}); //
}
  • 相关阅读:
    【算法系列】非线性最小二乘求解-梯度下降法
    SpringBoot实现指定时间开启定时任务
    基于java+springboot+mybatis+vue+elementui的灯具购物商城网站
    Opencore 常见kext驱动详解
    【洛谷 P1029】[NOIP2001 普及组] 最大公约数和最小公倍数问题 题解(辗转相除法)
    函数指针解释
    【Java 进阶篇】JDBC 数据库连接池详解
    Hutool基本用法介绍
    【owt】owt-client-native-p2p-e2e-test vs2017构建 3 : 无 测试单元对比, 手动生成vs项目
    选择排序(超详细)
  • 原文地址:https://www.cnblogs.com/known/p/17766595.html