### Define a variable for examples Source: https://github.com/axuno/smartformat/wiki/SubString _ SubStringFormatter This C# variable is used across multiple examples to demonstrate string formatting. ```csharp var person = new {Name = "Long John", City = "New York"}; ``` -------------------------------- ### Numeric Input Matching Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Demonstrates how the choose formatter matches numeric inputs against a list of choices to produce a corresponding output. Includes examples for exact matches and a default output when no match is found. ```CSharp Smart.Format("{0:choose(1|2|3):one|two|three|other}", 1); // outputs: "one" ``` ```CSharp Smart.Format("{0:choose(1|2|3):one|two|three|other}", 9); // outputs: "other" ``` ```CSharp Smart.Format("{0:choose(4.0|4.1|4.2):dot zero|dot one|dot two|other}", 4.1M); // outputs: "dot one" ``` -------------------------------- ### Sample HTML Content Source: https://github.com/axuno/smartformat/wiki/HTML-with-CSS-or-JavaScript This is an example of HTML content that includes embedded JavaScript and CSS, along with SmartFormat placeholders within the body. ```html
My name is {Name}. I'm living in {City}.
``` -------------------------------- ### Localize String with Placeholders Source: https://github.com/axuno/smartformat/wiki/Localization-_-LocalizationFormatter Shows how localized strings can contain placeholders. The example localizes a string containing a numeric placeholder for both English and Spanish cultures. ```CSharp Smart.Format("{0} {1:L(en):has {:#,#} inhabitants}", "X-City", 8900000); ``` ```CSharp Smart.Format("{0} {1:L(es):has {:#,#} inhabitants}", "X-City", 8900000); ``` -------------------------------- ### DefaultFormatter Simple Invocation Source: https://github.com/axuno/smartformat/wiki/Default _ DefaultFormatter Demonstrates implicit and explicit invocation of the DefaultFormatter for basic number formatting. Includes an example with CultureInfo. ```CSharp // implicit invokation Smart.Format("{0}", 1234); // explicit invokation by formatter name Smart.Format("{0:d}", 1234); // with CultureInfo Smart.Format(CultureInfo.GetCultureInfo("en-US"), "{0:d}", 1234); // all output: "1234" ``` -------------------------------- ### Get Members from Base Classes with ReflectionSource Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md ReflectionSource now includes members from base classes, providing more comprehensive data access. ```csharp ReflectionSource now also gets members from base classes ``` -------------------------------- ### Localize Nested Placeholders Source: https://github.com/axuno/smartformat/wiki/Localization-_-LocalizationFormatter Illustrates the support for nested placeholders within localized strings. The example shows how a placeholder within a localized string can itself be replaced and localized. ```CSharp Smart.Format("{:L(fr):{ProductType}}"); ``` -------------------------------- ### Extract a substring by start index and length Source: https://github.com/axuno/smartformat/wiki/SubString _ SubStringFormatter Extracts a substring of a specified length starting from a given index. Requires the input to be a string. ```csharp Smart.Format("{City:substr(0,3)}", person); ``` -------------------------------- ### ListFormatter with Spacers and Placeholders Source: https://github.com/axuno/smartformat/wiki/Lists _ ListFormatter Example of using placeholders within the spacer and finalSpacer of the ListFormatter to dynamically control the output based on boolean conditions or other variables. ```CSharp var args = new { Names = new[] { "John", "Mary", "Amy" }, IsAnd = true, // true or false Split = ", " // comma and space as list separator }; _ = Smart.Format("{Names:list:{}\{Split}\{IsAnd:and|nor} }", args); // Output for "IsAnd=true": "John, Mary and Amy" // Output for "IsAnd=false": "John, Mary nor Amy" ``` -------------------------------- ### Nesting Placeholders in SmartFormat Source: https://github.com/axuno/smartformat/wiki/Placeholders-and-Nesting Demonstrates how to use nesting in SmartFormat to avoid repetition when accessing deeply nested properties. The example shows accessing City and FirstName from a nested Person object. ```CSharp var person = new { Person = new { FirstName = "John", LastName = "Long", Address = new { City = "London", Street = "Main St" } } }; Smart.Format("City: {Person:{Address:{City}}, Name: {FirstName}}", person); ``` -------------------------------- ### Instantiate SmartFormatter with Settings Source: https://github.com/axuno/smartformat/wiki/Configuration Demonstrates the correct way to instantiate SmartFormatter with custom settings. Settings should be provided during instantiation and not modified afterward. ```Csharp // DO var sf = new SmartFormatter(new SmartSettings { CaseSensitivity = CaseSensitivityType.CaseInsensitive }); // DO NOT var sf = new SmartFormatter(); sf.Settings.CaseSensitivity = CaseSensitivityType.CaseInsensitive; ``` -------------------------------- ### Use Registered Templates for Formatting Source: https://github.com/axuno/smartformat/wiki/Templates-_-TemplateFormatter Demonstrates using registered templates with Smart.Format. It shows how to apply different templates based on arguments. ```Csharp var person = new { FirstName = "Joseph", Nickname = "Joe", LastName = "Doe" }; // Use the "master" template with different args // Informal Smart.Format("{0:t(salutation)}:", person, false); // Outputs "Hi Joe:" // Formal Smart.Format("{0:t(salutation)}:", person, true); // Outputs "Dear Mr Doe:" ``` -------------------------------- ### Extract a substring by start index Source: https://github.com/axuno/smartformat/wiki/SubString _ SubStringFormatter Extracts a substring starting from a specified index to the end of the string. Requires the input to be a string. ```csharp Smart.Format("{Name:substr(5)}", person); ``` -------------------------------- ### Using a FormatDelegate Source: https://github.com/axuno/smartformat/wiki/Default _ DefaultFormatter Illustrates formatting using a `FormatDelegate`, which allows custom formatting logic for indexed placeholders. Requires the `SmartFormat.Utilities` namespace. ```CSharp var amount = 123.456M; var c = new System.Globalization.CultureInfo("fr-FR"); // Only works for indexed placeholders var formatDelegate = new SmartFormat.Utilities.FormatDelegate((format, culture) => $"{format}: {amount.ToString(c)}"); Smart.Format("{0:The amount is}", formatDelegate); // Outputs: "The amount is: 123,456" ``` -------------------------------- ### Basic Smart.Format Usage Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Demonstrates basic string formatting with Smart.Format using positional arguments and anonymous objects. ```Csharp using SmartFormat; Smart.Format("{0} {1}", "Hello", "World") // outputs "Hello World" Smart.Format("{h} {w}", new{ h = "Hello", w = "World" }) // outputs "Hello World" ``` -------------------------------- ### Create Default SmartFormat Source: https://github.com/axuno/smartformat/wiki/Templates-_-TemplateFormatter Initializes the default SmartFormat instance. This is the first step before adding extensions. ```Csharp var formatter = Smart.CreateDefaultSmartFormat(); ``` -------------------------------- ### Smart.Format with Alignment and Item Format Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Demonstrates using alignment and item formatting to control padding and number representation. ```Csharp var data = new { Item = 9 }; Smart.Format("There are {Item,7:default:000} items", data); // Outputs: "There are 009 items" ``` -------------------------------- ### Output Only If Null Source: https://github.com/axuno/smartformat/wiki/Null-_-NullFormatter Use the NullFormatter to display a specific string only when the formatted value is null. This example shows formatting a null object. ```CSharp Smart.Format("{0:isnull:N/A}", default(object)); // outputs: "N/A" ``` -------------------------------- ### Using a Custom Localization Provider Source: https://github.com/axuno/smartformat/wiki/Localization-_-LocalizationFormatter Demonstrates how to configure SmartFormat to use a custom `ILocalizationProvider` and add the `LocalizationFormatter`. This allows for localized output using the custom provider. ```CSharp // Change settings for your provider Smart.Default.Settings.Localization.LocalizationProvider = new DictLocalizationProvider(); // Add the formatter Smart.Default.AddExtensions(new LocalizationFormatter()); Smart.Format("{:L(en):COUNTRY} * {:L(fr):COUNTRY} * {:L(es):COUNTRY}"); ``` -------------------------------- ### Specify Options for Named Formatters Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md Enables passing options to a named formatter, providing more control over formatting. Example: '{0:name(options): ___ }'. ```csharp {0:name(options): ___ } ``` -------------------------------- ### Basic SmartFormat Usage Source: https://github.com/axuno/smartformat/wiki/Home Demonstrates the basic usage of SmartFormat for string interpolation with named placeholders. Requires the SmartFormat library. ```C# var data = new { Library = "SmartFormat"}; _ = Smart.Format("Composed with {Library}.", data); // Result: "Composed with SmartFormat." ``` -------------------------------- ### String Input Matching (null, empty, value) Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Shows how the choose formatter handles string inputs, including null, empty strings, and other string values. It maps them to predefined outputs. ```CSharp Smart.Format("{0:choose(null|):null|empty|{}}", default(string?)) // outputs: "null" ``` ```CSharp Smart.Format("{0:choose(null|):null|empty|{}}", "") // outputs: "empty" ``` ```CSharp Smart.Format("{0:choose(null|):null|empty|{}}", "something else") // "something else" ``` -------------------------------- ### Use Named Formatters in SmartFormat.NET Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md Allows specifying a formatter by its name for targeted formatting. For example, '{0:plural: ___ }' uses the Plural formatter. ```csharp {0:plural: ___ } ``` ```csharp {0:default: ___ } ``` -------------------------------- ### SmartFormat Localization with StringFormatCompatibility Source: https://github.com/axuno/smartformat/wiki/string.Format Compatibility Demonstrates localization in SmartFormat by providing a CultureInfo object. This allows formatting numbers and dates according to specific cultural conventions, mirroring string.Format behavior. ```Csharp Smart.Format(CultureInfo.GetCultureInfo("en-US"), "{0:C}", 1234) // Outputs: "$1,234.00" Smart.Format(CultureInfo.GetCultureInfo("ja-JP"), "{0:C}", 1234) // Outputs: "1234" ``` -------------------------------- ### Registering Data Sources Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Demonstrates how to register source extensions with the SmartFormatter using AddExtensions and InsertExtension. ```APIDOC ## Register Data Sources Required `ISource` extensions must be registered with the `SmartFormatter`. Data sources are added by calling * `SmartFormatter.AddExtensions(...)` * `SmartFormatter.InsertExtension(...)` With `AddExtensions(...)` all `WellKnownExtensionTypes.Sources` and `WellKnownExtensionTypes.Formatters` are *automatically* inserted to the extension list at the place *where they usually should be*. `InsertExtension(...)` lets you insert an extension to the desired position in the list. From a performance perspective, only register source extensions that are actually needed: ```CSharp // Add needed source extensions var smart = new SmartFormatter() .AddExtensions(new ReflectionSource(), new DefaultSource()); // Add all default source extensions (and formatters) smart = Smart.CreateDefaultFormatter(); ``` ``` -------------------------------- ### Handle Multiple Elements with Same Name using XElementFormatter Source: https://github.com/axuno/smartformat/wiki/XML _ XElementFormatter XElementFormatter treats multiple elements with the same name as a list, enabling formatting with ConditionalFormatter or ListFormatter. This example demonstrates counting elements and listing them. ```CSharp var multiFirstName = XElement.Parse( "" + "Joe" + "Jack" + "Doe" + "Jim" + ""); var smart = Smart.CreateDefaultSmartFormat() .AddExtensions(new XElementFormatter()) .AddExtensions(new XmlSource()); // More xml elements with the same name are treated as a list // (used together with ConditionalFormatter) smart.Format("There {FirstName.Count:cond:is {} Doe |are {} Does}", multiFirstName); // Outputs: "There are 3 Does" // List FirstNames with ListFormatter smart.Format("{FirstName:list:|, | and }", multiFirstName); // Outputs: "Joe, Jack and Jim" ``` -------------------------------- ### Registering Source Extensions - SmartFormatter Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Demonstrates how to add needed source extensions to SmartFormatter. Use AddExtensions for specific sources or Smart.CreateDefaultFormatter() to include all default sources and formatters. ```CSharp // Add needed source extensions var smart = new SmartFormatter() .AddExtensions(new ReflectionSource(), new DefaultSource()); // Add all default source extensions (and formatters) smart = Smart.CreateDefaultFormatter(); ``` -------------------------------- ### Smart.Format with Selector Case Conversion Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Shows how to use selectors with methods like ToUpper and ToLower for case conversion within the format string. ```Csharp // More than 1 selector Smart.Format("{0.ToUpper} {1.ToLower}", "Hello", "World") // outputs "HELLO world" ``` -------------------------------- ### Boolean Input Matching Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Shows how to use the choose formatter with boolean inputs. Both 'True'/'False' and 'true'/'false' casing are accepted for matching. ```CSharp Smart.Format("{0:choose(True|False):yes|no}", true); ``` ```CSharp Smart.Format("{0:choose(true|false):yes|no}", true); // both output: "yes" ``` -------------------------------- ### Access Outer Scopes with Nested Scopes Feature Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md Enables nested templates to access outer scopes without workarounds. For example, in '{Person: {Address: {City} {FirstName} } }', '{City}' comes from 'Address' and '{FirstName}' from 'Person'. ```csharp {Person: {Address: {City} {FirstName} } } ``` -------------------------------- ### Compile-time Character Literal Conversion in C# and Smart.Format Source: https://github.com/axuno/smartformat/wiki/Character-Literals-in-Format-Strings When format strings originate from code, C# and Smart.Format automatically convert character literals to their Unicode representations. This example shows the TAB character being correctly interpreted by both `string.Format` and `Smart.Format`. ```Csharp string.Format("\t") Smart.Format("\t") // resulting character in both cases: TAB ``` -------------------------------- ### FormatSmart for string Source: https://github.com/axuno/smartformat/wiki/Extension-Methods Use string.FormatSmart for direct string formatting. Ensure SmartExtensions are imported. ```CSharp string.FormatSmart("template", args...); ``` -------------------------------- ### Configure PersistentVariablesSource Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Demonstrates how to set up and use PersistentVariablesSource to manage global variables for SmartFormatter. This involves creating VariablesGroup and Variable instances, adding them to the source, and registering the source with the SmartFormatter. ```CSharp // The top container // It gets its name later, when being added to the PersistentVariablesSource var varGroup = new VariablesGroup(); // Add a (nested) VariablesGroup named 'group' to the top container varGroup.Add("group", new VariablesGroup { // Add variables to the group { "groupString", new StringVariable("groupStringValue") }, { "groupDateTime", new Variable(new DateTime(2024, 12, 31)) } }); // Add more variables to the container varGroup.Add("topInteger", new IntVariable(12345)); varGroup.Add("topString", new StringVariable("topStringValue")); // The formatter for persistent variables requires only 2 extensions var smart = new SmartFormatter(); smart.FormatterExtensions.Add(new DefaultFormatter()); var pvs = new PersistentVariablesSource { // Here, the top container gets its name { "global", varGroup } }; // Best to put it to the top of source extensions smart.AddExtensions(0, pvs); // Note: We don't need args to the formatter for PersistentVariablesSource variables _ = smart.Format(CultureInfo.InvariantCulture, "{global.group.groupString} {global.group.groupDateTime:'groupDateTime='yyyy-MM-dd}"); // result: "groupStringValue groupDateTime=2024-12-31" _ = smart.Format("{global.topInteger}"); // result: "12345" _ = smart.Format("{global.topString}"); // result: "topStringValue" ``` -------------------------------- ### Conditional Formatting with ValueTuple Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Apply conditional logic within the format string to control output based on variable values. This example shows how to conditionally display 'ItemString' based on 'ItemInt' and 'ItemBool' values, keeping business logic out of the format string. ```CSharp Smart.Format("{Show:cond:{ItemString}|Don't show}", (data3, new { Show = data1.ItemInt == 123 && data2.ItemBool })); // Output: "an item" ``` -------------------------------- ### How Data Sources Work Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Explains the process of how SmartFormatter evaluates selectors and invokes registered ISources and IFormatters. ```APIDOC ## How do Data Sources Work The `SmartFormatter` evaluates the selectors in a `Placeholder` one by one. Fore each selector, the registered `ISource`s are invoked. As soon as an `ISource` can detect a matching variable from the data arguments, it returns the value. That's why the order in the list of registered data sources is important. If no matching data can be found for a `Placeholder` across all `ISource`s, a `FormattingException` will throw. After the selector was successfully evaluated, `IFormatter`(s) will be invoked. For `SmartSettings.CaseSensitivity == CaseSensitivityType.CaseInsensitive`, and multiple members share the same name but differ in case, the first encountered member will be selected. ``` -------------------------------- ### Format String Without Nullable Notation Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology When using SmartFormat, attempting to access members or methods on a potentially null object without explicit nullable notation in the format string will result in a FormattingException. This example shows the behavior when 'Name.ToUpper' is called on a null 'Name' property. ```Csharp Smart.Format("Name: {Name.ToUpper} - Birthday: {Birthday.Date:yyyy-MM-dd}", data); // Throws a FormattingException // Name: {Name.ToUpper} // ------------^ ``` -------------------------------- ### Smart.Format with Pluralization Formatter Options Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Illustrates using the PluralLocalizationFormatter with options to handle pluralization based on language. ```Csharp Smart.Format("{0:plural(en):zero|one|many}", 1); // outputs "one" for the English language option ``` -------------------------------- ### Accessing List Elements in Smart.Format Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Shows how to access elements within a list using index notation, either with square brackets or dot notation. ```Csharp var data = new {Numbers = new List{0,1,2,3}}; Smart.Format("{Numbers[1]}", data); Smart.Format("{Numbers.1}", data); // both output "1" ``` -------------------------------- ### Import AngleSharp Library Source: https://github.com/axuno/smartformat/wiki/HTML-with-CSS-or-JavaScript Include this using statement to leverage AngleSharp for HTML parsing. ```csharp using AngleSharp; ``` -------------------------------- ### Configure Extensions with GetFormatterExtension and GetSourceExtension Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md Provides methods to retrieve and configure formatter and source extensions for custom SmartFormatter behavior. ```csharp ```SmartFormatter.GetFormatterExtension``` and ```GetSourceExtension``` methods, which can be used to configure extensions ``` -------------------------------- ### SmartFormat Alignment with StringFormatCompatibility Source: https://github.com/axuno/smartformat/wiki/string.Format Compatibility Illustrates how to use alignment specifiers for left and right justification within a specified width in SmartFormat, similar to string.Format. ```Csharp Smart.Format("|{0,-10}|{1,10}|", "Left", "Right"); // Outputs: "|Left | Right|" ``` -------------------------------- ### SmartFormat vs. string.Format Source: https://github.com/axuno/smartformat/wiki/Home Compares SmartFormat with the built-in string.Format for identical formatting tasks. Useful for migrating or understanding compatibility. ```C# var stringFormat = string.Format("{0} {0:N2} {1:yyyy-MM-dd}", 5, new DateTime(1900, 12, 31)); var smartFormat = Smart.Format("{0} {0:N2} {1:yyyy-MM-dd}", 5, new DateTime(1900, 12, 31)); // Result: (stringFormat == smartFormat) == true ``` -------------------------------- ### Smart.Format with Nullable Notation - Basic Usage Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Demonstrates using nullable notation (?. ) to safely access properties that might be null, outputting an empty string by default. ```Csharp var data = new Person { Name = "Joe", Birthday = new DateTime(2000, 6, 30) }; Smart.Format("Name: {Name?.ToUpper} - Birthday: {Birthday?.Date:yyyy-MM-dd}", data); // Outputs: "Name: JOE - Birthday: 2000-06-30" data = new Person { Name = null, Birthday = null }; Smart.Format("Name: {Name?.ToUpper} - Birthday: {Birthday?.Date:yyyy-MM-dd}", data); // Outputs: "Name: - Birthday:" ``` -------------------------------- ### Enum Input Matching Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Illustrates matching enum values using the choose formatter. The formatter correctly maps enum members to their specified outputs. ```CSharp enum Gender { Female, Male, Unknown }; Smart.Format("{0:choose(Male|Female):his|her|their}", Gender.Female); // outputs: "her" ``` ```CSharp Smart.Format("{0:choose(Male|Female):his|her|their}", Gender.None); // outputs: "their" ``` -------------------------------- ### Register Default Formatters in C# Source: https://github.com/axuno/smartformat/wiki/How-Formatters-Work Demonstrates how to add source and formatter extensions to a SmartFormatter instance. Use this to manually register specific formatters or use Smart.CreateDefaultFormatter() to include all default extensions. ```csharp // Add needed source extensions var smart = new SmartFormatter() // Add source extensions .AddExtensions(new ReflectionSource(), new DefaultSource()) // Add formatter extensions .AddExtensions(new ListFormatter(), new DefaultFormatter); // Add all default source and formatter extensions smart = Smart.CreateDefaultFormatter(); ``` -------------------------------- ### Using Expressions in SmartFormat Placeholders Source: https://github.com/axuno/smartformat/wiki/Placeholders-and-Nesting Shows how SmartFormat supports expressions, such as calling parameterless methods like ToUpper and ToLower, within named placeholders. ```CSharp Smart.Format("{FirstName.ToUpper} {LastName.ToLower}", person) ``` -------------------------------- ### Format with KeyValuePair Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Use KeyValuePairSource for simple, performant named placeholders. The type arguments for KeyValuePair must be . ```csharp Smart.Format("{placeholder}", new KeyValuePair("placeholder", "some value") ``` -------------------------------- ### Register and Use Custom Formatter Source: https://github.com/axuno/smartformat/wiki/Creating-Your-Own-Extension Register the custom formatter using AddExtensions and invoke it within a format string. Ensure the formatter is added before attempting to use it in Smart.Format. ```CSharp Smart.Default.AddExtensions(new HelloFormatter()); Smart.Format("{value:hello(world):earth}", new { value = true }); // Outputs: "HELLO world" Smart.Format("{value:hello(world):earth}", new { value = false }); // Outputs: "HELLO earth" ``` -------------------------------- ### SmartFormat Extensions with ListFormatter Source: https://github.com/axuno/smartformat/wiki/string.Format Compatibility Demonstrates the use of SmartFormat extensions, such as the ListFormatter, when StringFormatCompatibility is disabled. This allows for advanced formatting of collections. ```Csharp var data = new [] {1, 2, 3}; _ = Smart.Format(@"{0:list:*{:N2}*| \: }", data); // Result: "*1,00* : *2,00* : *3,00*" ``` -------------------------------- ### Custom ILocalizationProvider Implementation Source: https://github.com/axuno/smartformat/wiki/Localization-_-LocalizationFormatter Provides a C# implementation of a custom `ILocalizationProvider` using a dictionary to store translations. This allows for flexible localization beyond standard resource files. ```CSharp public class DictLocalizationProvider : ILocalizationProvider { private readonly Dictionary> _translations; public DictLocalizationProvider() { _translations = new Dictionary> { { "en", new Dictionary { { "COUNTRY", "country" } } }, { "fr", new Dictionary { { "COUNTRY", "pays" } } }, { "es", new Dictionary { { "COUNTRY", "país" } } } }; } public string? GetString(string name) { return GetTranslation(name, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); } public string? GetString(string name, string cultureName) { return GetTranslation(name, cultureName); } public string? GetString(string name, CultureInfo cultureInfo) { return GetTranslation(name, cultureInfo.TwoLetterISOLanguageName); } private string? GetTranslation(string name, string cultureName) { if (!_translations.TryGetValue(cultureName, out var entry)) return null; return entry.TryGetValue(name, out var localized) ? localized : null; } } ``` -------------------------------- ### Argument Implementing IFormattable Source: https://github.com/axuno/smartformat/wiki/Default _ DefaultFormatter Shows how to format custom objects that implement the `IFormattable` interface. The `ToString` method is used with a provided format string. ```CSharp // A simple class public class FmtDemo : IFormattable { public string ToString(string? format, IFormatProvider? p) { return $"{format} implmenting IFormattable"; } } Smart.Format("{0:FmtDemo}", new FmtDemo()); // Outputs: "FmtDemo implementing IFormattable" ``` -------------------------------- ### Customizing Split Character and Case Sensitivity Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Shows how to change the default split character from '|' to ',' and set case sensitivity for the choose formatter. This allows more flexible formatting options. ```CSharp var chooseFmt = Smart.Default.GetFormatterExtension()!; chooseFmt.SplitChar = ','; chooseFmt.CaseSensitivity = CaseSensitivityType.CaseInsensitive; Smart.Format("{0:choose(one,two,three):|1|,|2|,|3|,|??|}", "TWO"); // outputs: "|2|" ``` -------------------------------- ### Formatting an IList with SmartFormat Source: https://github.com/axuno/smartformat/wiki/Home Shows how to format an IList using SmartFormat's list formatting capabilities. Specify custom delimiters and suffixes. ```C# var data = new [] {1, 2, 3, 4, 5}; _ = Smart.Format("{0:list:N2|, |, and }.", (object) data); // Result: "1.00, 2.00, 3.00, 4.00, and 5.00." ``` -------------------------------- ### ReflectionSource - Accessing Object Members Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Demonstrates using ReflectionSource to access object members like properties, fields, and parameterless methods. Caching is enabled by default for performance. ```CSharp Smart.Format("{Item}", new { Item = 999 }); ``` -------------------------------- ### Format with SystemTextJsonSource Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Use SystemTextJsonSource to format strings by accessing child elements of JElement. Requires the SmartFormat.Extensions.System.Text.Json NuGet package. ```csharp Smart.Format("{Name}", JsonDocument.Parse("{ \"Name\":\"John\"}").RootElement) ``` -------------------------------- ### ListFormatter - Formatting Lists Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Shows how to use ListFormatter to format collections like lists. It allows specifying custom separators and conjunctions for the list elements. ```CSharp Smart.Format("{0:list:{}|, and }", new List { "one", "two", "three" }); // Outputs: "one, two, and three" ``` -------------------------------- ### SmartFormat Item Formatting with StringFormatCompatibility Source: https://github.com/axuno/smartformat/wiki/string.Format Compatibility Shows how to format items like numbers and dates using SmartFormat with string.Format compatibility enabled. Custom format specifiers like 'N3' and 'MMMM, yyyy' are supported. ```Csharp Smart.Format("{0:N3} | {1:MMMM, yyyy}", 5.5, new DateTime(2010,3,4)); // Outputs: "5.500 | March, 2010" ``` -------------------------------- ### SmartFormat Indexed Placeholders with StringFormatCompatibility Source: https://github.com/axuno/smartformat/wiki/string.Format Compatibility Explains the use of indexed placeholders in SmartFormat, where numbers correspond to the argument index, identical to string.Format. ```Csharp Smart.Format("{0} {1}", "Hello", "World"); // Outputs: "Hello World" ``` -------------------------------- ### Culture-Aware Formatting with SmartFormat Source: https://github.com/axuno/smartformat/wiki/Common-Pitfalls Use Smart.Format with a CultureInfo object to ensure proper formatting of numbers, dates, and currency according to specific regional standards. ```CSharp Smart.Format(new CultureInfo("en-US"), "{0:C}", 1234) ``` -------------------------------- ### WriteSmart for TextWriter (Console) Source: https://github.com/axuno/smartformat/wiki/Extension-Methods Use WriteSmart with Console.Out to format strings directly to the console. Ensure SmartExtensions are imported. ```CSharp Console.Out.WriteSmart("template", args...); ``` -------------------------------- ### Null Input Matching Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Demonstrates matching null values with the choose formatter. The formatter handles 'null' and 'NULL' case-insensitively. ```CSharp Smart.Format("{0:choose(null): N/A|{}}", default(object)); ``` ```CSharp Smart.Format("{0:choose(NULL): N/A|{}}", default(object)); // both outputs: "N/A" ``` -------------------------------- ### Register a Simple Template Source: https://github.com/axuno/smartformat/wiki/Templates-_-TemplateFormatter Registers a template with a given name and content. The content can include placeholders like {variable}. ```Csharp templates.Register("SomeTemplate", "The template content: {variable}"); ``` -------------------------------- ### Nested Placeholder in Output Source: https://github.com/axuno/smartformat/wiki/Choose _ ChooseFormatter Illustrates using nested placeholders within the output of the choose formatter. This allows dynamic content generation based on the matched choice. ```CSharp Smart.Format("{0:choose(null): N/A|{}}", 1234); // outputs: "1234" ``` -------------------------------- ### Format with String Methods Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Utilize StringSource to apply built-in string manipulation methods like ToUpper, Trim, and ToBase64 during formatting. ```csharp Smart.Format("{0.ToUpper}", "lower") ``` ```csharp Smart.Format("{0.Length}", "A name") ``` ```csharp Smart.Format("{0.ToUpper}", "dış") ``` ```csharp Smart.Format("{0.ToUpperInvariant}", "dış") ``` ```csharp Smart.Format("{0.ToLower}", "DIŞ") ``` ```csharp Smart.Format("{0.ToLowerInvariant}", "DIŞ") ``` ```csharp Smart.Format("{0.TrimStart}", " abc") ``` ```csharp Smart.Format("{0.TrimEnd}", "abc ") ``` ```csharp Smart.Format("{0.Trim}", " abc ") ``` ```csharp Smart.Format("{0.Capitalize}", "word") ``` ```csharp Smart.Format("{0.CapitalizeWords}", "john DOE") ``` ```csharp Smart.Format("{0.ToBase64}", "xyz") ``` ```csharp Smart.Format("{0.FromBase64}", "eHl6") ``` ```csharp Smart.Format("{0.ToCharArray}", "abc") ``` -------------------------------- ### Combine Localization with Pluralization Source: https://github.com/axuno/smartformat/wiki/Localization-_-LocalizationFormatter Demonstrates using the LocalizationFormatter in conjunction with the pluralization formatter. This allows for culture-specific pluralization of localized strings. ```CSharp Smart.Format("{0:plural:{:L(en):{} item}|{:L(en):{} items}}", 0); ``` ```CSharp Smart.Format("{0:plural:{:L(fr):{} item}|{:L(fr):{} items}}", 0); ``` ```CSharp Smart.Format("{0:plural:{:L(fr):{} item}|{:L(fr):{} items}}", 200); ``` -------------------------------- ### Format with XmlSource Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Use XmlSource to format strings by accessing child elements of an XElement. Requires the SmartFormat.Extensions.Xml NuGet package. ```csharp Smart.Format("{Name}", XElement.Parse("Joe")); ``` -------------------------------- ### Format TimeSpan with TimeFormatter Source: https://github.com/axuno/smartformat/wiki/TimeSpan-_-TimeFormatter Demonstrates various formatting options for TimeSpan objects using the TimeFormatter. Ensure the TimeFormatter extension is registered before use. ```CSharp var args = new object[] { TimeSpan.Zero, new TimeSpan(1,1,1,1,1), new TimeSpan(0,2,0,2,0), new TimeSpan(3,0,0,3,0), new TimeSpan(0,0,0,0,4), new TimeSpan(5,0,0,0,0) }; // Register the TimeFormatter extension Smart.Default.AddExtensions(new TimeFormatter()); Smart.Format("{0:time(en):noless}", args); // Outputs: "0 seconds" Smart.Format("{1:time(en):hours}", args); // Outputs: "25 hours" Smart.Format("{1:time(en):hours minutes}", args); // Outputs: "25 hours 1 minute" Smart.Format("{2:time(en):days milliseconds}", args); // Outputs: "2 hours 2 seconds" Smart.Format("{2:time(en):days milliseconds auto}", args); // Outputs: "2 hours 2 seconds" Smart.Format("{2:time(en):days milliseconds short}", args); // Outputs: "2 hours" Smart.Format("{2:time(en):days milliseconds fill}", args); // Outputs: "2 hours 0 minutes 2 seconds 0 milliseconds" Smart.Format("{2:time(en):days milliseconds full}", args); // Outputs: "0 days 2 hours 0 minutes 2 seconds 0 milliseconds" Smart.Format("{3:time(en):abbr}", args); // Outputs: "3d 3s" ``` -------------------------------- ### Implement IFormatter for Custom Formatting Source: https://github.com/axuno/smartformat/wiki/Creating-Your-Own-Extension Create a class implementing IFormatter to define custom logic for evaluating formats. The TryEvaluateFormat method determines if the formatter can handle the input and performs the output writing. ```CSharp public class HelloFormatter : IFormatter { public string Name { get; set; } = "hello"; public bool CanAutoDetect { get; set; } = true; public bool TryEvaluateFormat(IFormattingInfo formattingInfo) { var iCanHandleThisInput = formattingInfo.CurrentValue is bool; if (!iCanHandleThisInput) return false; formattingInfo.Write("HELLO "); if ((bool) formattingInfo.CurrentValue) formattingInfo.Write(formattingInfo.FormatterOptions); else formattingInfo.Write(formattingInfo.Format.GetLiteralText()); return true; } } ``` -------------------------------- ### List Matching Regex Group Values with IsMatch Source: https://github.com/axuno/smartformat/wiki/RegEx _ IsMatchFormatter Shows how to use the 'm' placeholder (configurable via PlaceholderNameForMatches) to list all captured regex group values when IsMatchFormatter is successful. The 'm' placeholder provides access to the GroupCollection. ```CSharp KeyValuePair arg = new("theValue", "Some123Content"); Smart.Format("{theValue:ismatch(^.+\(1\)\(2\)\(3\).+$):Matches for '{}'\\: {m:list:| - }|No match}", arg); // Outputs: "Matches for 'Some123Content': Some123Content - 1 - 2 - 3" ``` -------------------------------- ### Use Alternative Braces for Templates Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md Allows templates to utilize alternative characters for braces, providing flexibility in format string design. ```csharp ```UseAlternativeBraces``` method, so that templates can use alternative characters ``` -------------------------------- ### Format String with Multiple Objects Source: https://github.com/axuno/smartformat/wiki/Data Source Extensions Use indexed arguments to reference properties from different objects passed as separate arguments to Smart.Format. ```CSharp var data1 = new { ItemInt = 123 }; var data2 = new { ItemBool = true }; var data3 = new { ItemString = "an item" }; Smart.Format("{0.ItemInt} * {1.ItemBool} * {2.ItemString}", data1, data2, data3 ); // Outputs: "123 * True * an item" ``` -------------------------------- ### Indexed Placeholders with string.Format and SmartFormat Source: https://github.com/axuno/smartformat/wiki/Placeholders-and-Nesting Compares the use of indexed placeholders in C#'s string.Format and SmartFormat. Both achieve the same result by referencing arguments by their position. ```CSharp string.Format("{0} {1}", person.FirstName, person.LastName) ``` ```CSharp Smart.Format("{0} {1}", person.FirstName, person.LastName) ``` -------------------------------- ### Conditional Output with Gender Formatting Source: https://github.com/axuno/smartformat/wiki/Home Illustrates using SmartFormat's 'choose' formatter for conditional output based on a value, commonly used for gendered pronouns. ```C# var data = new[] { new { Name = "John", Gender = 0 }, new { Name = "Mary", Gender = 1 } }; _ = Smart.Format("{Name} commented on {Gender:choose:his|her} photo", data[1]); // Result: "Mary commented on her photo" ``` -------------------------------- ### Localize Literal to Spanish Source: https://github.com/axuno/smartformat/wiki/Localization-_-LocalizationFormatter Demonstrates how to localize a literal string to Spanish using the LocalizationFormatter. The culture can be specified directly in the format string or passed as an argument. ```CSharp Smart.Format("{:L(es):WeTranslateText}"); ``` ```CSharp var culture = CultureInfo.GetCultureInfo("es"); Smart.Format(culture, "{:L:WeTranslateText}"); ``` -------------------------------- ### Recommended TimeFormatter Format (v3+) Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md This format string is recommended for SmartFormat v3 and later. It allows for including the language as an option to the TimeFormatter. ```csharp // Without language option: var formatRecommended = "{0:time:abbr hours noless:}"; // With language option: var formatRecommended = "{0:time(en):abbr hours noless:}"; ``` -------------------------------- ### Smart.Format with Nullable Notation and IsNullFormatter Source: https://github.com/axuno/smartformat/wiki/Syntax,-Terminology Shows how to use the IsNullFormatter with nullable notation to provide default values when properties are null. ```Csharp // Or nicer by using the IsNullFormatter: Smart.Format("Name: {Name?.ToUpper:isnull:n/a|{}} - Birthday: {Birthday?.Date:isnull:n/a|{:yyyy-MM-dd}}", data) // Outputs: "Name: n/a - Birthday: n/a" ``` -------------------------------- ### Named Placeholders in SmartFormat Source: https://github.com/axuno/smartformat/wiki/Placeholders-and-Nesting Demonstrates using named placeholders in SmartFormat, which allows referencing object properties directly by their names instead of their index. ```CSharp Smart.Format("{FirstName} {LastName}", person) ``` -------------------------------- ### Parse HTML and Format with SmartFormat using AngleSharp Source: https://github.com/axuno/smartformat/wiki/HTML-with-CSS-or-JavaScript This C# code demonstrates pre-processing HTML with AngleSharp to correctly format content containing placeholders, scripts, and styles using SmartFormat. ```csharp var variables = new { Name = "John Long", City = "New York" }; // Create a new parser front-end (can be re-used) var parser = new AngleSharp.Html.Parser.HtmlParser(); // Get the DOM representation AngleSharp.Html.Dom.IHtmlDocument htmlDocument = parser.ParseDocument(html); // ##### Smart.Format the HTML body: ##### htmlDocument.Body.InnerHtml = Smart.Format(htmlDocument.Body.InnerHtml, variables); // This gets the complete HTML as a string var result = htmlDocument.ToHtml(); ``` -------------------------------- ### Synchronize Two Lists with ListFormatter Source: https://github.com/axuno/smartformat/wiki/Lists _ ListFormatter Illustrates synchronizing and formatting elements from two different lists (char array and string array) using indexed placeholders and the ListFormatter. ```CSharp var letters = "ABC".ToCharArray(); var words = "One|Two|Three".Split('|'); // works with indexed and named placeholders Smart.Format("{0:list:{}\, = {1[Index]}|, }", letters, words); // outputs: "A = One, B = Two, C = Three" ``` -------------------------------- ### Enable String.Format Compatibility in SmartFormat Source: https://github.com/axuno/smartformat/blob/main/CHANGES.md Set SmartSettings.StringFormatCompatibility to true to enable full compatibility with string.Format. Note that this may prevent custom formatter extensions from being parsed. ```csharp SmartSettings.StringFormatCompatibility = true; ``` -------------------------------- ### Format Simple Array with ListFormatter Source: https://github.com/axuno/smartformat/wiki/Lists _ ListFormatter Demonstrates formatting a simple array of strings using the ListFormatter. Note the explicit cast to IList is required for indexed parameters. ```CSharp var items = new[] { "one", "two", "three" }; // Important: You cannot use "items" as an indexed parameter directly, // as it would be used as params with 3 args. // So we have to cast var result = Smart.Format("{0:list:{}\, |\, and }", (IList) items); // Outputs: "one, two, and three" ```