Skip to content

Latest commit

 

History

History
74 lines (50 loc) · 4.83 KB

README.md

File metadata and controls

74 lines (50 loc) · 4.83 KB

Singulink.Text.TokenFormatter

Chat on Discord View nuget packages Build and Test

TokenFormatter provides simple yet versatile tokenized string formatting, designed primarily for processing localized resource strings, exception messages and log data in a more friendly manner than brittle positional tokens in the string.Format() family of methods. This can be particularly useful when utilizing localized resource strings since your translaters will have much better context when they see values like "{User.Name} performed {Action}" instead of "{0} performed {1}".

About Singulink

We are a small team of engineers and designers dedicated to building beautiful, functional and well-engineered software solutions. We offer very competitive rates as well as fixed-price contracts and welcome inquiries to discuss any custom development / project support needs you may have.

This package is part of our Singulink Libraries collection. Visit https://github.com/Singulink to see our full list of publicly available libraries and other open-source projects.

Installation

Simply install the Singulink.Text.TokenFormatter package from NuGet into your project.

Supported Runtimes: Anywhere .NET Standard 2.0+ is supported, including:

  • .NET Core 2.0+
  • .NET Framework 4.6.1+
  • Mono 5.4+
  • Xamarin.iOS 10.14+
  • Xamarin.Android 8.0+

Usage

The only two types exposed by the package are TokenFormatter and TokenOptions. TokenFormatter has the following two static methods that do it all:

string Format(string format, object tokenValues, TokenOptions options = default);
string Format(string format, object tokenValues, IFormatProvider? formatProvider, TokenOptions options = default);

Format strings contain token declarations inside curly braces. The simplest form of this just contains a token key, i.e. {TokenKey}. Token keys are used as string keys if tokenValues is an IDictionary otherwise they map to property names on other object types.

Tokens can contain subkeys seperated by dots (.) which will grab nested values, e.g. {User.FirstName.Length}. Tokens can also contain an optional format string following a colon (:), e.g. {Transaction.Amount:C2}.

Finally, any key or subkey can have a question mark (?) appended to it to indicate that the value may be null, e.g. {User.MiddleName?.Length}. If you do not indicate that a token value can be null then a NullReferenceException is thrown when a null value is encountered. Null values are simply replaced with an empty string by default, but you can specify a replacement string when the value is null by putting it after the question mark, like so: {User?[unknown user].MiddleName?*no middle name*.Length}. This example would output the string "[unknown user]" if the User key returns a null value or "*no middle name*" if the MiddleName subkey returns a null value.

Curly braces are escaped by doubling them up, so "{{" and "}}" are formatted as "{" and "}", respectively. The inside of a token declaration cannot contain any curly braces anywhere. Additionally, token keys cannot contain question marks (?) or colons (:) as they are interpreted as nullability indicators and token format delimiters, respectively.

TokenOptions has three available values:

  • None - the default value with no options set.
  • NonPublicAccess - Indicates non-public properties can be accessed from tokens.
  • AllowMissingKeys - Indicates that nullable keys that don't exist should be treated like null instead of throwing KeyNotFoundException.

Examples

The following are some examples to demonstrate how TokenFormatter works:

using Singulink.Text;

User? currentUser = GetCurrentlyLoggedInUser();
string url = HttpContext.Current.Request.Url;

// "[anonymous] just visited website.com"
// "mikernet just visited website.com"
TokenFormatter.Format("{User?[anonymous].Name} just visited {Url}", new { User = currentUser, Url = url });

var info = new Dictionary<string, object> {
  [Name] = "Mike",
  [Age] = 35,
  [Address] = new { Street = "123 Easy Street", City = "London", State = "ON" },
  [Income] = 99999.99m,
}

// "Mike (age 35) lives at 123 Easy Street, London, ON"
TokenFormatter.Format("{Name} (age {Age}) lives at {Address.Street}, {Address.City}, {Address.State}", info);

// "{Mike has an income of $99,999.99 and drives (?)}"
TokenFormatter.Format("{{{Name} has an income of {Income:C2} and drives {Car?(?)}}}", info, TokenOptions.AllowMissingKeys);