Расширенное форматирование для стандартных плейсхолдеров
Расширенное форматирование для стандартных плейсхолдеров¶
Пусть требуется изменить поведение стандартных плейсхолдеров {f:...}
и {fv:...}
, добавив в них обработку нестандартной строки формата. Например, чтобы можно было указать {f:DocumentCommonInfo.Subject:reverse}
, и на место плейсхолдера была бы подставлена тема документа с обратным порядком символов. Системе неизвестна строка форматирования reverse
, но её можно определить следующим образом.
В сборке Tessa.Extensions.Shared создаём класс-наследник FieldPlaceholderReplacer
, который является обёрткой для любого IFieldPlaceholderReplacer
(такой есть у {f:...}
и {fv:...}
).
using System;
using System.Threading;
using System.Threading.Tasks;
using Tessa.Platform.Placeholders;
public sealed class AdditionalFormattingFieldPlaceholderReplacer : FieldPlaceholderReplacer
{
public AdditionalFormattingFieldPlaceholderReplacer(IFieldPlaceholderReplacer replacer)
{
this.replacer = replacer;
}
private readonly IFieldPlaceholderReplacer replacer;
protected override async Task<PlaceholderValue> ReplaceCoreAsync(IPlaceholderReplacementContext context, IPlaceholder placeholder, CancellationToken cancellationToken = default)
{
// если передана известная нам строка форматирования, но неизвестная стандартному форматтеру,
// то мы передаём в replacer плейсхолдер с указанием format = null
IPlaceholder replacerPlaceholder =
placeholder.Format == "reverse"
? new Placeholder(placeholder.Type, null, placeholder.Parameters, placeholder)
: placeholder;
PlaceholderValue result = await this.replacer.ReplaceAsync(context, replacerPlaceholder, cancellationToken);
if (result == null)
{
return null;
}
if (placeholder.Format == "reverse")
{
// изменяем порядок символов на обратный
string text = result.Text;
char[] charArray = text.ToCharArray();
Array.Reverse(charArray);
text = new string(charArray);
return new PlaceholderValue(text, result.Fields);
}
return result;
}
}
Для плейсхолдеров-таблиц аналогично потребуется переопределить регистрацию типов {t:...}
и {tv:...}
, задав TablePlaceholderType
с указанием TablePlaceholderReplacerNames
, причём потребуется создать отдельный класс-наследник TablePlaceholderReplacer
.
using System;
using System.Threading;
using System.Threading.Tasks;
using Tessa.Platform.Placeholders;
public class AdditionalFormattingTablePlaceholderReplacer : TablePlaceholderReplacer
{
public AdditionalFormattingTablePlaceholderReplacer(ITablePlaceholderReplacer replacer)
{
this.replacer = replacer;
}
private readonly ITablePlaceholderReplacer replacer;
protected override string GetTableNameCore(IPlaceholderReplacementContext context, IPlaceholder placeholder)
{
return this.replacer.GetTableName(context, placeholder);
}
protected override Task FillTableCoreAsync(IPlaceholderReplacementContext context, IPlaceholder placeholder, IEditablePlaceholderTable table, CancellationToken cancellationToken = default)
{
return this.replacer.FillTableAsync(context, placeholder, table, cancellationToken);
}
protected override async Task<PlaceholderValue> ReplaceCoreAsync(IPlaceholderReplacementContext context, IPlaceholder placeholder, IPlaceholderRow row, CancellationToken cancellationToken = default)
{
// если передана известная нам строка форматирования, но неизвестная стандартному форматтеру,
// то мы передаём в replacer плейсхолдер с указанием format = null
IPlaceholder replacerPlaceholder =
placeholder.Format == "reverse"
? new Placeholder(placeholder.Type, null, placeholder.Parameters, placeholder)
: placeholder;
PlaceholderValue result = await this.replacer.ReplaceAsync(context, replacerPlaceholder, row, cancellationToken);
if (result == null)
{
return null;
}
if (placeholder.Format == "reverse")
{
// изменяем порядок символов на обратный
string text = result.Text;
char[] charArray = text.ToCharArray();
Array.Reverse(charArray);
text = new string(charArray);
return new PlaceholderValue(text, result.Fields);
}
return result;
}
}
И регистрируем плейсхолдеры в классе Registrator
, переопределяя стандартные плейсхолдеры.
using System;
using Tessa.Extensions;
using Tessa.Platform.Placeholders;
using Unity;
[Registrator]
public sealed class Registrator : RegistratorBase
{
public override void FinalizeRegistration()
{
this.UnityContainer
.Resolve<IPlaceholderContainer>()
// переопределяем {f:...}
// пример использования: {f:Section.Field:reverse}
.Register(new FieldPlaceholderType("f", true, () =>
new AdditionalFormattingFieldPlaceholderReplacer(
this.UnityContainer.Resolve<IFieldPlaceholderReplacer>(
FieldPlaceholderReplacerNames.Default))),
overrideType: true)
// переопределяем {fv:...}
// пример использования: {fv:ColumnAlias:reverse}
.Register(new FieldPlaceholderType("fv", true, () =>
new AdditionalFormattingFieldPlaceholderReplacer(
this.UnityContainer.Resolve<IFieldPlaceholderReplacer>(
FieldPlaceholderReplacerNames.View))),
overrideType: true)
// переопределяем {t:...}
// пример использования: {t:Section.Field:reverse}
.Register(new TablePlaceholderType("t", true, () =>
new AdditionalFormattingTablePlaceholderReplacer(
this.UnityContainer.Resolve<ITablePlaceholderReplacer>(
TablePlaceholderReplacerNames.Default))),
overrideType: true)
// переопределяем {tv:...}
// пример использования: {tv:ColumnAlias:reverse}
.Register(new TablePlaceholderType("tv", true, () =>
new AdditionalFormattingTablePlaceholderReplacer(
this.UnityContainer.Resolve<ITablePlaceholderReplacer>(
TablePlaceholderReplacerNames.View))),
overrideType: true)
;
}
}
Плейсхолдеры с расширенным форматированием можно будет использовать везде, где можно использовать стандартные плейсхолдеры, например: в формате полного номера, в имени последовательности, в формате дайджеста для типа карточки, и в любых файловых шаблонах (Word, Excel, Html), в т.ч. с вынесением плейсхолдера в алиасы.