再学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#之基础知识,故作一随笔,也是对此前几篇博客中所记录的传值参数相关内容之汇总,还望诸位加以批评指正. 该博客包括以下内容: 传值参数 引用参数 输出参数 数组参数 具名参数 可选参数 扩展 ...
随机推荐
- Swift函数调用方式浅析
函数的调用机制 函数的调用机制是在函数调用时通过那种路径走到最终调用函数地址的机制. 在编程语言中,函数的调用机制有三种 1.静态调用:编译期就确定了函数内存地址,执行效率最高,还可以使用编译器优 ...
- Linux 如何删除乱码的文件
事情是这样,服务器很多人在使用,以前的离职同事留了一大堆不知道是什么东西. 那些文件看不了,又删不掉,非常碍眼. 我搜索了挺多资料,没有一篇文章能真的解决问题(感觉都是抄来抄去的). 用 SFTP 工 ...
- Nginx配置网站默认https
Nginx配置网站默认https 一.安装Nginx yum install nginx -y 二.修改nginx.conf vim /etc/nginx/nginx.conf 配置80转443 配置 ...
- spring cloud微服务搭建配置中心之携程开源框架Apollo
1.Apollo(阿波罗) Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适 ...
- OpenCV4之特征提取与对象检测
1.图像特征概述 图像特征的定义与表示 图像特征表示是该图像唯一的表述,是图像的DNA 图像特征提取概述 传统图像特征提取 - 主要基于纹理.角点.颜色分布.梯度.边缘等 深度卷积神经网络特征提取 - ...
- Java程序员的MacBookPro(14寸M1)配置备忘录
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 欣宸的月俸虽然很低,但还是咬着牙攒够银子,入 ...
- 好用的css3特性-过渡和2D变换
css3中有很多非常好用的特性,今天来总结一下与动画相关,包括过渡.2D变换. 首先来介绍一下过渡,过渡是在进行变化的时候进行的一个缓冲,如果没有过渡,当变更了元素的位置.大小的数据时,会一瞬间完成变 ...
- Javascript执行原理 网页引入javascript的三种方式* javascript核心语法 数据类型 Typeof运算符
Javascript执行原理: 用户端发送请求到服务器端 将js解析出来的数据(用户身份表示)绑定在请求路径中 服务器端获取到参数后会响应客户端 客户端通过浏览器解析响应的数据并将数据展现在浏览器上 ...
- jmeter对请求响应结果进行整段内容提取方法
通过正则表达式提取器,将上一个请求(A请求)响应数据中的整段内容提取,传给下一个需要该提取数据的请求(B请求). 1. 请求接口响应结果 2. 添加正则表达式提取器 设置变量名为"tt&qu ...
- 解决WSL执行systemctl命令报错:Failed to get D-Bus connection
问题描述 笔者通过WSL安装了CentOS7系统,刚开始一切都很顺利.当执行systemctl命令时,却意外报错:Failed to get D-Bus connection: Operation n ...