Решение
Помимо метода Process()
, базовый тег-помощник также предоставляет метод Init()
.Это резюме:
Инициализирует Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper
с заданным контекстом.В этот метод необходимо добавить Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext.Items
, чтобы они были добавлены до выполнения дочерних процессов.
Просто переопределите этот метод и добавьте все, что вам нужно:
public override void Init(TagHelperContext context)
{
context.Items.Add(1, "Init FormTagHelper");
}
Объяснение
Для вашего html-кода:
<form my-attr='Hello'>
<input asp-for='SomeProperty' />
</form>
у нас будет два помощника по тегам:
FormTagHelper
[HtmlTargetElement("form")]
public class FormTagHelper : TagHelper
{
public override void Init(TagHelperContext context)
{
context.Items.Add(1, "Init FormTagHelper");
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
context.Items.Add(4, "Process FormTagHelper");
}
}
InputTagHelper
[HtmlTargetElement("input")]
public class InputTagHelper : TagHelper
{
public override void Init(TagHelperContext context)
{
context.Items.Add(2, "Init InputTagHelper");
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
context.Items.Add(3, "Process InputTagHelper");
}
}
Чтобы лучше понять в каком порядке вызываются методы , давайте взглянем на эту диаграмму:
Я думаю, что порядок исполнения довольно очевиден.Но как насчет красной No access
части?Давайте начнем с определения, что такое словарь Items
и как он работает.Он фигурирует как IDictionary<object, object>
, но это не обычный словарь.Это CopyOnWriteDictionary
, и это совершенно особенное.У него есть два базовых словаря ReadDictionary
и WriteDictionary
, и он вызывает любой из них в зависимости от того, какой тип действия (чтение / запись) выполняется в данный момент.
Хотя вы можете добавить 1
из FormTagHelper.Init()
вы не сможете получить доступ к ключам 2
и 3
из FormTagHelper.Process()
, несмотря на то, что согласно диаграмме они уже должны быть там:
Это потому, что значения для InputTagHelper
добавляются к _innerDictionary
, а не _sourceDictionary
, который затем используется в FormTagHelper
.Такое поведение создает односторонний доступ к словарю Items
.Помощники тегов Children могут получить доступ к значениям, добавленным родителями, но не наоборот.
Состояние словаря Items
после выполнения Init()
метода InputTagHelper()
: