Ecng.SmartFormat 1.0.41

dotnet add package Ecng.SmartFormat --version 1.0.41
                    
NuGet\Install-Package Ecng.SmartFormat -Version 1.0.41
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ecng.SmartFormat" Version="1.0.41" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ecng.SmartFormat" Version="1.0.41" />
                    
Directory.Packages.props
<PackageReference Include="Ecng.SmartFormat" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ecng.SmartFormat --version 1.0.41
                    
#r "nuget: Ecng.SmartFormat, 1.0.41"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ecng.SmartFormat@1.0.41
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ecng.SmartFormat&version=1.0.41
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.SmartFormat&version=1.0.41
                    
Install as a Cake Tool

SmartFormat - Advanced String Formatting Library

SmartFormat is a lightweight, extensible string formatting library that extends the capabilities of string.Format. It provides powerful templating features including conditional formatting, pluralization, list formatting, and more.

Features

  • All features of string.Format plus advanced extensions
  • Conditional formatting (if/else logic)
  • Pluralization and localization support
  • List formatting with customizable separators
  • Time and TimeSpan formatting
  • Nested object property access
  • Dictionary and JSON source support
  • XML/XElement support
  • Template-based formatting
  • Extensible architecture with custom formatters and sources
  • High performance with caching support

Installation

Add a reference to the SmartFormat project in your solution.

Quick Start

Basic Usage

using SmartFormat;

// Simple formatting (like string.Format)
string result = Smart.Format("Hello {0}!", "World");
// Output: Hello World!

// Named placeholders
string result = Smart.Format("Hello {Name}!", new { Name = "Alice" });
// Output: Hello Alice!

Object Property Access

var person = new { Name = "John", Age = 30, Address = new { City = "New York" } };

string result = Smart.Format("{Name} is {Age} years old and lives in {Address.City}.", person);
// Output: John is 30 years old and lives in New York.

Core Formatters

Conditional Formatter

Format strings based on conditions:

// Syntax: {value:condition(true-text|false-text)}
string result = Smart.Format("{0:cond:>=18?Adult|Minor}", 25);
// Output: Adult

string result = Smart.Format("{0:cond:>0?Positive|Zero or Negative}", -5);
// Output: Zero or Negative

Plural Formatter

Automatically handles pluralization:

// Syntax: {value:plural:singular|plural}
string result = Smart.Format("You have {Count:plural:one item|{} items}.", new { Count = 1 });
// Output: You have one item.

string result = Smart.Format("You have {Count:plural:one item|{} items}.", new { Count = 5 });
// Output: You have 5 items.

// Advanced pluralization
string result = Smart.Format("{Count:plural:no items|one item|{} items}", new { Count = 0 });
// Output: no items

List Formatter

Format collections with custom separators:

var numbers = new[] { 1, 2, 3, 4, 5 };

// Default separator (comma)
string result = Smart.Format("{0:list:{}|, }", numbers);
// Output: 1, 2, 3, 4, 5

// Custom separators
string result = Smart.Format("{0:list:{} and {}|, | and }", new[] { "Alice", "Bob", "Charlie" });
// Output: Alice, Bob and Charlie

// With index
var items = new[] { "Apple", "Banana", "Cherry" };
string result = Smart.Format("{0:list:{Index}: {Item}|, }", items);
// Output: 0: Apple, 1: Banana, 2: Cherry

Choose Formatter

Select output based on value:

// Syntax: {value:choose(option1|option2|option3):case1|case2|case3}
string result = Smart.Format("{Status:choose(0|1|2):Pending|Active|Completed}", new { Status = 1 });
// Output: Active

// With string matching
string result = Smart.Format("{Day:choose(Mon|Tue|Wed|Thu|Fri|Sat|Sun):Weekday|Weekday|Weekday|Weekday|Weekday|Weekend|Weekend}",
    new { Day = "Sat" });
// Output: Weekend

Time Formatter

Format TimeSpan values in human-readable form:

var timeSpan = TimeSpan.FromHours(2.5);

string result = Smart.Format("{0:time}", timeSpan);
// Output: 2 hours 30 minutes

string result = Smart.Format("{0:time:short}", TimeSpan.FromSeconds(90));
// Output: 1m 30s

string result = Smart.Format("{0:timespan:h' hours 'm' minutes'}", TimeSpan.FromMinutes(125));
// Output: 2 hours 5 minutes

SubString Formatter

Extract substrings:

string text = "Hello World";

// Get first N characters
string result = Smart.Format("{0:substr(0,5)}", text);
// Output: Hello

// Get last N characters
string result = Smart.Format("{0:substr(-5)}", text);
// Output: World

Advanced Features

Dictionary Support

var dict = new Dictionary<string, object>
{
    ["Name"] = "Alice",
    ["Age"] = 30,
    ["City"] = "Boston"
};

string result = Smart.Format("{Name} is {Age} years old and lives in {City}.", dict);
// Output: Alice is 30 years old and lives in Boston.

Nested Templates

var data = new
{
    User = "John",
    Items = new[] { "Apple", "Banana", "Orange" }
};

string result = Smart.Format("{User}'s shopping list: {Items:list:{} ({Index})|, }", data);
// Output: John's shopping list: Apple (0), Banana (1), Orange (2)

Combining Formatters

var orders = new[] { 1, 2, 3 };

string result = Smart.Format("You have {0:list:{} order|, }.", orders);
// Output: You have 1 order, 2 order, 3 order.

string result = Smart.Format("You have {Count:plural:no orders|one order|{} orders}.", new { Count = orders.Length });
// Output: You have 3 orders.

Conditional with Nested Objects

var user = new
{
    Name = "Alice",
    Premium = true,
    Credits = 100
};

string result = Smart.Format("{Name}: {Premium:cond:Premium Member ({Credits} credits)|Standard Member}", user);
// Output: Alice: Premium Member (100 credits)

Extension Methods

StringBuilder Extensions

using System.Text;
using SmartFormat;

var sb = new StringBuilder();

sb.AppendSmart("Hello {Name}!", new { Name = "World" });
// StringBuilder now contains: Hello World!

sb.AppendLineSmart("Value: {0}", 42);
// StringBuilder now contains: Hello World!Value: 42\n

TextWriter Extensions

using System.IO;
using SmartFormat;

using (var writer = new StreamWriter("output.txt"))
{
    writer.WriteSmart("Hello {Name}!", new { Name = "World" });
    writer.WriteLineSmart("Count: {0}", 5);
}

String Extensions

using SmartFormat;

string template = "Hello {Name}!";
string result = template.FormatSmart(new { Name = "Alice" });
// Output: Hello Alice!

Performance Optimization

Using Format Cache

For frequently used format strings, use caching to improve performance:

using SmartFormat.Core.Formatting;

FormatCache cache = null;
string template = "Hello {Name}, you are {Age} years old.";

// First call - parses and caches the template
string result1 = template.FormatSmart(ref cache, new { Name = "Alice", Age = 30 });

// Subsequent calls - reuses cached parse result (faster)
string result2 = template.FormatSmart(ref cache, new { Name = "Bob", Age = 25 });
string result3 = template.FormatSmart(ref cache, new { Name = "Charlie", Age = 35 });

Direct SmartFormatter Usage

using SmartFormat;

var formatter = Smart.Default;

// Reuse the same formatter instance
string result1 = formatter.Format("{0} + {1} = {2}", 1, 2, 3);
string result2 = formatter.Format("{Name} is here", new { Name = "Alice" });

Custom Configuration

Creating a Custom Formatter

using SmartFormat;
using SmartFormat.Extensions;

// Create a formatter with only specific extensions
var formatter = new SmartFormatter();

// Add source extensions
formatter.AddExtensions(
    new ReflectionSource(formatter),
    new DictionarySource(formatter),
    new DefaultSource(formatter)
);

// Add formatter extensions
formatter.AddExtensions(
    new DefaultFormatter(),
    new PluralLocalizationFormatter("en"),
    new ConditionalFormatter()
);

string result = formatter.Format("Hello {Name}!", new { Name = "World" });

Accessing Extensions

// Get a specific formatter extension
var pluralFormatter = Smart.Default.GetFormatterExtension<PluralLocalizationFormatter>();
if (pluralFormatter != null)
{
    // Configure the formatter
    // ...
}

// Get a specific source extension
var reflectionSource = Smart.Default.GetSourceExtension<ReflectionSource>();

Error Handling

Error Actions

Configure how format errors are handled:

using SmartFormat.Core.Settings;

var formatter = new SmartFormatter();
formatter.Settings.FormatErrorAction = ErrorAction.OutputErrorInResult;  // Default
// or
formatter.Settings.FormatErrorAction = ErrorAction.ThrowError;
// or
formatter.Settings.FormatErrorAction = ErrorAction.Ignore;
// or
formatter.Settings.FormatErrorAction = ErrorAction.MaintainTokens;

Error Event Handling

Smart.Default.OnFormattingFailure += (sender, args) =>
{
    Console.WriteLine($"Formatting error: {args.ErrorMessage}");
};

Complete Examples

User Notification System

var notification = new
{
    UserName = "Alice",
    UnreadMessages = 5,
    Friends = new[] { "Bob", "Charlie", "Diana" },
    IsPremium = true
};

string message = Smart.Format(
    @"{UserName}, you have {UnreadMessages:plural:no new messages|one new message|{} new messages}.
{IsPremium:cond:Premium features are enabled.|Upgrade to premium!}
Your friends: {Friends:list:{}|, | and }.",
    notification);

// Output:
// Alice, you have 5 new messages.
// Premium features are enabled.
// Your friends: Bob, Charlie and Diana.

Report Generation

var report = new
{
    Title = "Sales Report",
    Date = DateTime.Now,
    TotalSales = 15234.50m,
    Items = new[]
    {
        new { Product = "Widget A", Quantity = 150, Price = 29.99m },
        new { Product = "Widget B", Quantity = 200, Price = 19.99m },
        new { Product = "Widget C", Quantity = 75, Price = 49.99m }
    }
};

string output = Smart.Format(
    @"{Title} - {Date:yyyy-MM-dd}
Total Sales: ${TotalSales:N2}

Items:
{Items:list:{Product}: {Quantity} units @ ${Price:N2} each|
}",
    report);

Localized Messages

var orderInfo = new
{
    ItemCount = 3,
    Status = 1,  // 0=Pending, 1=Shipped, 2=Delivered
    EstimatedDays = 2
};

string message = Smart.Format(
    @"{ItemCount:plural:one item|{} items} - Status: {Status:choose(0|1|2):Pending|Shipped|Delivered}
{Status:cond:>=1?Estimated delivery in {EstimatedDays:plural:one day|{} days}.|Processing your order.}",
    orderInfo);

// Output: 3 items - Status: Shipped
// Estimated delivery in 2 days.

Async Support

using System.Threading;
using SmartFormat;

var data = new { Name = "Alice", Value = 42 };

string result = await Smart.FormatAsync("{Name}: {Value}", new object[] { data }, CancellationToken.None);
// Output: Alice: 42

Migration from string.Format

SmartFormat is designed to be a drop-in replacement for string.Format:

// string.Format
string old = string.Format("Hello {0}, you are {1} years old.", "Alice", 30);

// SmartFormat (same syntax works)
string new1 = Smart.Format("Hello {0}, you are {1} years old.", "Alice", 30);

// SmartFormat (enhanced syntax)
string new2 = Smart.Format("Hello {Name}, you are {Age} years old.", new { Name = "Alice", Age = 30 });

Target Frameworks

  • .NET Standard 2.0
  • .NET 6.0
  • .NET 10.0

License

Copyright (C) axuno gGmbH, Scott Rippey, Bernhard Millauer and other contributors. Licensed under the MIT license.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Ecng.SmartFormat:

Package Downloads
Ecng.Common

Ecng system framework

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.41 1,719 12/21/2025
1.0.40 1,158 12/19/2025
1.0.39 10,844 12/12/2025
1.0.38 13,968 11/20/2025
1.0.37 102,053 11/7/2024
1.0.36 16,407 9/18/2024
1.0.35 30,777 5/4/2024
1.0.34 7,286 4/14/2024
1.0.33 13,562 2/23/2024
1.0.32 31,390 1/2/2024
1.0.31 62,292 9/8/2023
1.0.30 53,260 6/29/2023
1.0.29 48,918 5/8/2023
1.0.28 61,202 4/3/2023
1.0.27 32,265 3/6/2023
1.0.26 68,046 2/9/2023
1.0.25 22,601 2/7/2023
1.0.24 7,083 2/4/2023
1.0.23 26,932 2/2/2023
1.0.22 22,813 1/30/2023
1.0.21 59,986 12/30/2022
1.0.20 33,690 12/12/2022
1.0.19 41,446 11/30/2022
1.0.18 51,918 11/11/2022
1.0.17 8,001 11/11/2022
1.0.16 14,550 11/5/2022
1.0.15 38,499 11/1/2022
1.0.14 37,702 10/16/2022
1.0.13 69,417 9/8/2022
1.0.12 9,601 9/8/2022
1.0.11 9,720 9/8/2022
1.0.10 108,226 8/24/2022
1.0.9 29,276 7/26/2022
1.0.8 9,583 7/26/2022
1.0.7 61,054 7/19/2022
1.0.6 54,065 7/18/2022
1.0.5 130,630 4/30/2022
1.0.4 54,896 3/29/2022
1.0.3 457,914 12/29/2021
1.0.2 34,805 12/20/2021
1.0.1 109,035 11/29/2021
1.0.0 34,327 11/22/2021

Added comprehensive README.md documentation for all projects