我正在开发一个ASP.NET Core MVC 1.1应用程序,我正在努力寻找一种干净有效的解决方案,将decimal
格式化为自定义货币代码的货币(即与CultureInfo
中指定的不同)。
目前,我有以下decimal
扩展类:
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);
}
}
我目前的解决方案包括两部分:
CultureInfo
属性创建新的CurrencySymbol
实例。可悲的是,我不喜欢这两部分。
对于第一部分,我可以将映射放入appsettings.json
并填充Dictionary
类中的Startup
。但是,我仍然希望完全跳过这个并迭代系统支持的文化和货币。但是,正如我已经完成的研究,这在ASP.NET Core MVC 1.1中尚不可能。
对于第二部分,我根本不喜欢Clone()
部分。由于CultureInfo.CurrentCulture
是只读的,我 可能必须在某个时候克隆它,但最好不要在每次调用我的扩展方法时。
有没有办法缓存克隆和更改的CultureInfo
?由于这是一个扩展类,我想依赖注入是不合适的。
答案 0 :(得分:2)
如果您仍在寻找答案,我已经调整了您的扩展方法来缓存克隆的文化信息对象。
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);
}
}