Global Formatting Made Easy with IFormattable in .NET 8 for Enterprise Applications
Tags: dotnet, programming, csharp, dotnet8
Published: 2024-02-29 22:09:00

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
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2tv7nqqrqz08y6feuxh.png)

## 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.

```csharp
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);
}
```

## 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.

```csharp
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.")
        };
    }

    // ...
}
```

## 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.

```csharp
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);
    }
}
```

## 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 `MoneyFormatter `utility, 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](https://gist.github.com/admir-live/63ed3a6e6b7fca101a3f5df4b053884b)

---
Cheers! 👋

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