DEV Community

Admir Mujkic
Admir Mujkic

Posted on

Global Formatting Made Easy with IFormattable in .NET 8 for Enterprise Applications

In today’s interconnected world, enterprise applications must cater to diverse user bases spanning multiple regions and cultures. One critical aspect often overlooked is the presentation of financial data, where nuances in formatting can greatly impact user experience and data accuracy.

In this blog post, we’ll explore how the Money class, implemented in .NET 8 and leveraging the IFormattable interface, revolutionizes global financial data presentation, ensuring consistency and cultural relevance across various locales.

Global Formatting Made Easy with IFormattable in .NET 8 for Enterprise Applications<br>

Understanding the Money Class

The Money class serves as a cornerstone for representing monetary values within enterprise applications. It encapsulates both the amount and currency code, providing a robust and immutable data structure for financial transactions.

By utilizing the record feature introduced in .NET 8, the Money class benefits from built-in immutability, value-based equality, and straightforward syntax for object creation and manipulation.

public record Money(decimal Amount, string CurrencyCode) : IFormattable
{
    private static MoneyFormatter Formatter { get; } = new();

    public string ToString(string? format, IFormatProvider? formatProvider) =>
        MoneyFormatter.Format(this, format, formatProvider);
}
Enter fullscreen mode Exit fullscreen mode

Cultural Compatibility with IFormattable

At the heart of the Money class lies the implementation of the IFormattable interface. This interface allows the Money objects to be formatted into string representations tailored to the cultural preferences of users worldwide.

Whether it's displaying currency symbols, decimal separators, or thousands grouping, the IFormattable interface ensures that monetary values are presented accurately and intelligibly across different regions.

public sealed class MoneyFormatter
{
    private static ConcurrentDictionary<string, string> CurrencySymbolsCache { get; } = new();

    public static string Format(Money money, string? format, IFormatProvider? formatProvider)
    {
        formatProvider ??= CultureInfo.CurrentCulture;
        format = EnsureValidFormat(format);

        return format.ToUpperInvariant() switch
        {
            "N" => FormatAsNumber(money, formatProvider),
            "C" => FormatAsCurrency(money, formatProvider),
            _ => throw new FormatException($"The {format} format string is not supported.")
        };
    }

    // ...
}
Enter fullscreen mode Exit fullscreen mode

Testing with xUnit and FluentAssertions

To validate the functionality of the Money class and MoneyFormatter, comprehensive unit tests are imperative. Leveraging the xUnit testing framework along with FluentAssertions, we rigorously test the formatting logic across various cultural scenarios.

using System.Globalization;
using Xunit;
using FluentAssertions;

public class MoneyTests
{
    [Theory]
    [InlineData(1234.56, "USD", "en-US", "1,234.56 USD")]
    [InlineData(1234.56, "EUR", "de-DE", "1.234,56 EUR")]
    public void Money_ToString_FormatsCorrectlyForGivenCulture(decimal amount, string currencyCode, string culture, string expected)
    {
        // Arrange
        var money = new Money(amount, currencyCode);
        var cultureInfo = new CultureInfo(culture);

        // Act
        var result = money.ToString("N", cultureInfo);

        // Assert
        result.Should().Be(expected);
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In an increasingly globalized business landscape, the ability to present financial data accurately and culturally relevantly is paramount. Through the implementation of the Money class and MoneyFormatterutility, our enterprise applications can now seamlessly accommodate diverse user bases worldwide.

By embracing the principles of cultural compatibility and meticulous testing, we pave the way for enhanced user experiences and empowered decision-making in the realm of global finance.

If you looking for source code, please check next link


Cheers! 👋

Follow me on LinkedIn: www.linkedin.com/comm/mynetwork/discovery-see-all?usecase=PEOPLE_FOLLOWS&followMember=admir-live

Top comments (0)