Перейти к содержанию

Форматтер для плейсхолдеров

Форматтер для плейсхолдеров

Для плейсхолдеров можно зарегистрировать форматтер, позволяющий либо сделать постобработку текстового значения, либо представить данные в отличном от строки виде, например, в виде изображения. По умолчанию форматтер работает для любых плейсхолдеров, выполняющих форматирование через объект IPlaceholderFormatter. По умолчанию в платформе эту возможность используют все плейсхолдеры, в т.ч. {f:...}, {t:...}, {fv:...}, {tv:...}, {cardLink}, {date} и др.

Note

Форматтеры для плейсхолдеров доступны, начиная со сборки 2.5.2.

Для примера напишем форматтер #reverse, который меняет порядок символов в тексте на обратный. Форматтер регистрируется в проекте Tessa.Extensions.Shared, чтобы быть доступным как на клиенте (для форматирования Digest карточки), так и на сервере (в файловых шаблонах и всех других случаях).

using System.Linq; using System.Threading; using System.Threading.Tasks; using Tessa.Platform.Placeholders; using Unity; using Unity.Lifetime;

namespace Tessa.Extensions.Shared.Placeholders { public class ReversePlaceholderFormatter : PlaceholderFormatterBase { protected override async ValueTask<string> FormatFieldTextAsync( IPlaceholderReplacementContext context, IPlaceholder placeholder, IPlaceholderFormatSettings formatSettings, IPlaceholderFormatRequest request, CancellationToken cancellationToken = default) { string text = await base.FormatFieldTextAsync(context, placeholder, formatSettings, request, cancellationToken); return string.IsNullOrEmpty(text) ? text : new string(text.Reverse().ToArray()); } }

[Registrator] public sealed class Registrator : RegistratorBase { public override void RegisterUnity() { this.UnityContainer .RegisterType<ReversePlaceholderFormatter>(new ContainerControlledLifetimeManager()) ; }

public override void FinalizeRegistration() { this.UnityContainer .Resolve<IPlaceholderFormatterContainer>() .Register("reverse", this.UnityContainer.Resolve<ReversePlaceholderFormatter>()) ; } } }

Пример использования: {f:DocumentCommonInfo.Subject:#reverse}

Чтобы заменить плейсхолдер на изображение, можно переопределить базовый метод FormatFieldCore.

Форматтер также может иметь обязательные или опциональные параметры, доступные посредством метода formatSettings.GetCustomFormatParameters(). В плейсхолдерах они задаются как {f:DocumentCommonInfo.Subject:#reverse(key=value;option1;option2)}, где key - это строковый параметр со значением value, а option1 и option2 - ключи со значениями bool (если присутствуют, то имеют значение true).

Форматтер может использовать зависимости из контейнера Unity как получив их из конструктора (один раз за время работы приложения), так и из контекста context (каждый раз при выполнении метода форматирования). Например, если требуется из уникального идентификатора получить ссылку на открытие карточки в web-клиенте вида https://address.org/tessa/web/tessa/card/12d8cf28-9902-4dfd-8cbc-0f8a4d994691, то можно написать форматтер #webCardLink, который использует настройки из ICardCache для определения адреса веб-клиента.

Посредством такого форматтера можно преобразовать идентификатор исходящего документа в ссылку, которую отобразить в виде QR-кода: {t:OutgoingRefDocs.DocID:#webCardLink;qrcode(t=url)}

using System; using System.Threading; using System.Threading.Tasks; using Tessa.Cards; using Tessa.Cards.Caching; using Tessa.Platform.Placeholders; using Unity;

namespace Tessa.Extensions.Shared.Placeholders { public class WebCardLinkPlaceholderFormatter : PlaceholderFormatterBase { protected override async ValueTask<string> FormatFieldTextAsync( IPlaceholderReplacementContext context, IPlaceholder placeholder, IPlaceholderFormatSettings formatSettings, IPlaceholderFormatRequest request, CancellationToken cancellationToken = default) { IUnityContainer unityContainer = context.TryGetUnityContainer(); if (unityContainer != null && unityContainer.IsRegistered<ICardCache>() && request.Field.Value is Guid cardID) { ICardCache cardCache = unityContainer.Resolve<ICardCache>(); string webAddress = await CardHelper.TryGetWebAddressAsync(cardCache, cancellationToken: cancellationToken);

if (!string.IsNullOrEmpty(webAddress)) { return CardHelper.GetWebLink(webAddress, cardID, normalize: false); } }

return null; } }

[Registrator] public sealed class Registrator : RegistratorBase { public override void FinalizeRegistration() { this.UnityContainer .Resolve<IPlaceholderFormatterContainer>() .Register("webCardLink", new WebCardLinkPlaceholderFormatter(), true) ; } } }

Note

Такой форматтер уже содержится в типовом решении, поэтому в методе регистрации указан overrideFormatterName: true.

Аналогично можно написать плейсхолдер, который может использовать возможности форматтеров. Например, плейсхолдер {webCardLink:#qrcode(t=url)}, отображающий ссылку на текущую карточку в виде QR-кода.

using System; using System.Threading; using System.Threading.Tasks; using Tessa.Cards; using Tessa.Cards.Caching; using Tessa.Platform.Placeholders; using Unity;

namespace Tessa.Extensions.Shared.Placeholders { public static class PlaceholderHelper { public static async Task<PlaceholderValue> ReplaceWebCardLinkAsync( IPlaceholderReplacementContext context, IPlaceholder placeholder, CancellationToken cancellationToken = default) { Guid? cardID = await context.TryGetCardIDAsync(); IUnityContainer unityContainer;

if (!cardID.HasValue || (unityContainer = context.TryGetUnityContainer()) == null || !unityContainer.IsRegistered<ICardCache>()) { return null; }

ICardCache cardCache = unityContainer.Resolve<ICardCache>(); string webAddress = await CardHelper.TryGetWebAddressAsync(cardCache, cancellationToken: cancellationToken);

if (string.IsNullOrEmpty(webAddress)) { return null; }

string text = CardHelper.GetWebLink(webAddress, cardID.Value, normalize: false); return await context.FormatTextAsync(placeholder, text, cancellationToken: cancellationToken); } }

[Registrator] public sealed class Registrator : RegistratorBase { public override void FinalizeRegistration() { this.UnityContainer .Resolve<IPlaceholderContainer>() .Register(new FieldPlaceholderType("webCardLink", PlaceholderHelper.ReplaceWebCardLinkAsync), true) ; } } }

Note

Такой плейсхолдер уже содержится в типовом решении, поэтому в методе регистрации указан overrideType: true.

Back to top