Ecng.SmartFormat
1.0.41
dotnet add package Ecng.SmartFormat --version 1.0.41
NuGet\Install-Package Ecng.SmartFormat -Version 1.0.41
<PackageReference Include="Ecng.SmartFormat" Version="1.0.41" />
<PackageVersion Include="Ecng.SmartFormat" Version="1.0.41" />
<PackageReference Include="Ecng.SmartFormat" />
paket add Ecng.SmartFormat --version 1.0.41
#r "nuget: Ecng.SmartFormat, 1.0.41"
#:package Ecng.SmartFormat@1.0.41
#addin nuget:?package=Ecng.SmartFormat&version=1.0.41
#tool nuget:?package=Ecng.SmartFormat&version=1.0.41
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.Formatplus 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 | Versions 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. |
-
.NETStandard 2.0
- Newtonsoft.Json (>= 13.0.4)
- System.Threading.Tasks.Extensions (>= 4.6.3)
-
net10.0
- Newtonsoft.Json (>= 13.0.4)
-
net6.0
- Newtonsoft.Json (>= 13.0.4)
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