简体   繁体   中英

Format currency with custom currency code (ASP.NET Core MVC)

I am developing a ASP.NET Core MVC 1.1 application and I am struggling to find a clean and efficient solution for formatting decimal as currency with custom currency code (ie different than specified in the CultureInfo ).

Currently, I have the following decimal extension class:

public static class DecimalExtensions
{
  public static readonly Dictionary<string, string> CurrencyCodeToSymbol = new Dictionary<string, string>() {
    { "EUR", "€"},
    { "USD", "$"},
    { "GBP", "£"},
  };

  public static string FormatCurrency(this decimal decimalValue, string currencyCode)
  {
    var culture = (CultureInfo) CultureInfo.CurrentCulture.Clone();
    culture.NumberFormat.CurrencySymbol = CurrencyCodeToSymbol[currencyCode];
    return decimalValue.ToString("C", culture);
  }
}

My current solution consists of two parts:

  1. Mapping from currency code to currency symbol.
  2. Creating a new CultureInfo instance with the right CurrencySymbol property.

Sadly, I don't like either part.

For the first part, I could put the mapping into appsettings.json and fill the Dictionary in the Startup class. However, I would still prefer to skip this altogether and iterate over system supported cultures and currencies. However, as I have done my research, this is not yet possible in ASP.NET Core MVC 1.1.

For the second part, I don't like the Clone() part at all. Since the CultureInfo.CurrentCulture is readonly, I will probably have to clone it at some point, but preferably not at each call to my extension method.

Is there any way to cache the cloned and altered CultureInfo ? Since this is an extension class, I guess Dependency Injection is out of the picture.

If you are still looking for an answer, I've tweaked your extension method to cache the cloned culture info objects.

public static class DecimalExtensions
{
    private static readonly IDictionary<String, String> _currencyCodeToSymbol = new Dictionary<String, String>
    {
        { "EUR", "€"},
        { "USD", "$"},
        { "GBP", "£"},
    };

    private static readonly ConcurrentDictionary<String, CultureInfo> _currencyCodeToLocale =
        new ConcurrentDictionary<String, CultureInfo>();

    public static String FormatCurrency(this Decimal decimalValue, String currencyCode = "USD")
    {
        if (!_currencyCodeToSymbol.ContainsKey(currencyCode))
        {
            throw new NotImplementedException($"Currency code {currencyCode} is not supported");
        }

        var cultureInfo = _currencyCodeToLocale.GetOrAdd(currencyCode, _ =>
        {
            var info = CultureInfo.CurrentCulture.Clone() as CultureInfo;
            info.NumberFormat.CurrencySymbol = _currencyCodeToSymbol[currencyCode];
            return info;
        });

        return decimalValue.ToString("C", cultureInfo);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM