上一篇文章中提到有时候须要设计一种内嵌的TagHelper,以下:html
<my name="yy" age="35"> <location country="China" city="Shanghai" district="PuDong"></location> </my>
location就是一个内嵌的TagHelper,咱们能够在location里设置与它相关的Attributes,有时候设置有多层内嵌的TagHelper。那么怎样设计出这样的一个内嵌的TagHelper来呢?其实它和通常的TagHelper没什么的区别,你们能够利用前面咱们介绍的来设计出它的TagHelper类及Attributes。和通常的TagHelper的主要区别是,它和父TagHelper关联。如何创建这种关联?这也是这章咱们须要搞清楚的。异步
经过前面章节学习,咱们知道设计的自定义TagHelper类都会继承于抽象类TagHelper,在这个类中有二个方法:ide
//同步处理 public virtual void Process(TagHelperContext context, TagHelperOutput output); //异步处理 public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
通常咱们会根据实际状况来选择重载哪一个方法。在TagHelper抽象类中,异步处理是调用同步处理方法。在这两个方法中参数相同,在这里详细介绍第一个参数context。学习
它的类型是TagHelperContext,主要是存放TagHelper相关的信息:this
AllAttributesspa
TagHelper支持的全部Attribute集合,它是只读的。设计
Itemshtm
类型是IDictionary<object, object>,它是用来和其余TagHelper进行联系枢纽,对象
/// <summary> /// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s. /// </summary> /// <remarks> /// This <see cref="IDictionary{object, object}"/> is copy-on-write in order to ensure items added to this /// collection are visible only to other <see cref="ITagHelper"/>s targeting child elements. /// </remarks> public IDictionary<object, object> Items { get; }
从上面的描述能够看出,这个集合是copy-on-write,也就是说当前TagHelper在Items获取父TagHelper中的Items信息,也能够修改,删除或者添加某一项,可是不会影响到父TagHelper的Items值,同时也会将修改后的Items信息传给其子TagHelper,子TagHelper的任何修改不会影响到它。blog
在上面咱们提到,设计支持内嵌TagHelper类,关键是要创建父子TagHelper的联系,看到这里,我想你们都应该清楚如何创建这种关联。对了,就是利用context中Items。
主要是在TagHelper的Process方法中作如下事情。
public virtual void Process(TagHelperContext context, TagHelperOutput output) { // 从context.items获取父TagHelper信息 // 处理自身Attributes // 将自身信息存放在context.items中 // 处理本身的子TagHelper }
更具体的例子以下:
//定义父TagHelper public class PersonTagHelper : TagHelper { public string Name { get { return Person.Name; } set { Person.Name = value; } } public int Age { get { return Person.Age; } set { Person.Age = value; } } private Person _person; private Person Person { get { return _person ?? (_person = new Person()); } set { _person = value; } } public override void Process(TagHelperContext context, TagHelperOutput output) { // 保存信息给子TagHelper使用 context.Items["Parent"] = Person; // 执行并获取子TagHelper内容 context.GetChildContentAsync(); // 输出html元素和启动脚本 // 这里会用到第二个参数output,后面会介绍到如何使用。 } } // 定义子TagHelper public class LocationTagHelper: TagHelper { public string Country { get; set; } public string City { get; set; } public string District { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { // 获取来自父TagHelper的信息,并保存到变量里去 var parent = context.Items["Parent"] as Person; // 处理Attributes的设置 parent.Location.Country = Country; parent.Location.City = City; parent.Location.District = District; // 保存自身信息,便于子TagHelper使用 context.Items["Parent"] = parent.Location; // 执行并获取子TagHelper内容 context.GetChildContentAsync(); } } // 定义了父TagHelper中对应的对象实例 // 你们能够根据各自需求,决定是否须要定义这样一个类型 public class Person { public string Name { get; set; } public int Age { get; set; } private Location _location; public Location Location { get { return _location ?? (_location = new Location()); } } } // 定义子TagHelper中数据类型 // 你们能够根据各自需求,决定是否须要定义这样一个类型 public class Location { public string Country { get; set; } public string City { get; set; } public string District { get; set; } }
对于类Person和Location的定义你们能够根据具体状况来决定是否须要。
这个例子只是简单展现如何利用Items信息来构建父子TagHelper间的联系,你们在具体的项目开发中根据实际需求,写出不同的代码来,但有一点不变,就是要利用Items。