再学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,打开一个元素,呈现
<div>等开始标签 - CloseElement,关闭一个元素,呈现
</div>等关闭标签 - OpenComponent,打开一个组件,呈现
<MyComponent> - CloseComponent,关闭一个组件,呈现
</MyComponent> - 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<AttributeBuilder> 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<AttributeBuilder> child) => builder.Element("div", child);
...
}
下面写一个元素扩展方法的示例,并将呈现的 HTML 结构与 C# 代码进行比对,直观感受一下高级写法的妙处。
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.Div(attr => //<div id="myPanel" class="panel">
{ //
attr.Id("myPanel").Class("panel"); //
builder.Div(attr => // <div class="header">
{ //
attr.Class("header"); //
//这里构造 Panel 头部内容 //
}); // </div>
builder.Div(attr => // <div class="body">
{ //
attr.Class("body"); //
//这里构造 Panel 身体内容 //
}); // </div>
}); //</div>
}
再次优化一下扩展方法的示例,下面代码看起来是不是更整齐了一些。
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.Div("myPanel", "panel", attr => //<div id="myPanel" class="panel">
{ //
builder.Div("header", attr => // <div class="header">
{ //
//这里构造 Panel 头部内容 //
}); // </div>
builder.Div("body", attr => // <div class="body">
{ //
//这里构造 Panel 身体内容 //
}); // </div>
}); //</div>
}
再学Blazor——扩展方法的更多相关文章
- ASP.NET MVC学前篇之扩展方法、链式编程
ASP.NET MVC学前篇之扩展方法.链式编程 前言 目的没有别的,就是介绍几点在ASP.NETMVC 用到C#语言特性,还有一些其他琐碎的知识点,强行的划分一个范围的话,只能说都跟MVC有关,有的 ...
- 一个利用扩展方法的实例:AttachDataExtensions
扩展方法是C# 3.0(老赵对VB不熟)中最简单,也是最常用的语言特性之一.这是老赵自以为的一个简单却不失经典的实例: [AttributeUsage(AttributeTargets.All, Al ...
- 从扩展方法到匿名方法再到LINQ
1.首先我们应该知道什么是扩展方法: 扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样 ...
- (转)再不用担心DataRow类型转换和空值了(使用扩展方法解决高频问题)
再不用担心DataRow类型转换和空值了(使用扩展方法解决高频问题) XML文档操作集锦(C#篇) webapi文档描述-swagger
- 再谈扩展方法,从string.IsNullOrEmpty()说起
string.IsNullOrEmpty()这个方法算得上是.net中使用频率最高的方法之一.此方法是string的一个静态方法,类似的静态方法在string这个类中还有很多.那么这样的方法作为静态方 ...
- 再不用担心DataRow类型转换和空值了(使用扩展方法解决高频问题)
在使用DataRow读取数据时,通常会遇到数据可能为Null, 但是又需要转换为如int等其它类型的数据,因此就通常会写这样的代码: if (dr[name] != DBNull.Value & ...
- .NET 扩展方法 (一)
我还记得刚刚学编程的时候,老师经常会提到一句话:注意空指针.所以经常在某些“入口”位置,进行代码校验,空指针的判断就是其中的一项工作. string类型作为常用的数据类型,它在项目中出现的机率极高,所 ...
- 【C】 01 - 再学C语言
“C语言还用再学吗?嵌入式工程师可是每天都在用它,大家早就烂熟于心,脱离语言这个层面了”.这样说不无道理,这门古老的语言以其简单的语法.自由的形式的而著称.使用C完成工作并不会造成太大困扰,所以很少有 ...
- [C#详解] (1) 自动属性、初始化器、扩展方法
文章来源:Slark.NET-博客园 http://www.cnblogs.com/slark/p/CSharp-focus-1.html 代码下载:点我下载 目录 前言 属性与自动属性 属性 自动属 ...
- C#——各种参数,扩展方法
余近日复习C#之基础知识,故作一随笔,也是对此前几篇博客中所记录的传值参数相关内容之汇总,还望诸位加以批评指正. 该博客包括以下内容: 传值参数 引用参数 输出参数 数组参数 具名参数 可选参数 扩展 ...
随机推荐
- Kubernetes(k8s) Web-UI界面(一):部署和访问仪表板(Dashboard)
目录 一.系统环境 二.前言 三.仪表板(Dashboard)简介 四.部署Kubernetes仪表板(Dashboard) 五.访问Kubernetes仪表板(Dashboard) 5.1 使用to ...
- Go 并发模型—Goroutines
前言 Goroutines 是 Go 语言主要的并发原语.它看起来非常像线程,但是相比于线程它的创建和管理成本很低.Go 在运行时将 goroutine 有效地调度到真实的线程上,以避免浪费资源,因此 ...
- 基于Avalonia 11.0.0+ReactiveUI 的跨平台项目开发1-通用框架
基于Avalonia 11.0.0+ReactiveUI 的跨平台项目开发1-通用框架 Avalonia简介: Avalonia是.NET的一个跨平台UI框架,提供了一个灵活的样式系统,支持广泛的操作 ...
- Linux快速安装流量监控工具(实用版)
前言: Linux流量监控工具,在此我推荐两种分别为: 1.nload(推荐)因为个人看着舒服点 2.iftop 以上两种任选其一即可,在此对两种都有介绍和安装教程,我写了,大家随意哈 nload安装 ...
- 2023-7-26 Dynamic替代部分反射的简单实现方式
Dynamic与反射的使用 [作者]长生 实体类 public class School{ public int GetAge(){ return 100; } } 使用反射获取对象里的方法 Scho ...
- 清理MySQL的binlog日志
前言 MySQL的binlog是以二进制形式打印的日志,没设置自动删除的话,时间长了就会占用大量存储空间.删除MySQL的binlog日志有两种方法:自动删除和手动删除. 自动删除 永久生效:修改My ...
- Stable Diffusion基础:ControlNet之人体姿势控制
在AI绘画中精确控制图片是一件比较困难的事情,不过随着 ControlNet 的诞生,这一问题得到了很大的缓解. 今天我就给大家分享一个使用Stable Diffusion WebUI + OpenP ...
- 史上最强.NET数据分页方法
[前言] 本文讲述的.NET数据分页方法为[史上最强],已被多家大型科技公司实战采用 & 也被圈内多家知名IT培训机构转载收藏. [正文] 支持.Net Core(2.0及以上)与.Net F ...
- AI绘画| 迪士尼风格|可爱头像【附Midjourney提示词】
Midjourney案例分享 图片预览 迪士尼风格|可爱头像 高清原图及关键词Prompt已经放在文末网盘,需要的自取 在数字艺术的新时代,人工智能绘画已经迅速崭露头角.作为最先进的技术之一,AI绘画 ...
- 《最新出炉》系列入门篇-Python+Playwright自动化测试-15-playwright处理浏览器多窗口切换
1.简介 浏览器多窗口的切换问题相比大家不会陌生吧,之前宏哥在java+selenium系列文章中就有介绍过.大致步骤就是:使用selenium进行浏览器的多个窗口切换测试,如果我们打开了多个网页,进 ...