c# - 尝试实现自定义格式化程序,但从未调用 ICustomFormatter.Format

标签 c# iformatprovider

在遵循 Format TimeSpan in DataGridView column 之后,我试图弄清楚 IFormatProvider 和 ICustomFormatter 是如何工作的关于如何在 DataGridView 中自定义 TimeSpan。我创建了一个完全自定义的格式化程序,无论它的格式如何,它总是返回“foo”。

我在 Int 上使用它,但我认为它应该适用于所有类型,因为它不检查传递的值,它只返回 "foo"

class MyFormatter : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        Console.WriteLine("GetFormat");
        return this;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        Console.WriteLine("Format");
        return "foo";
    }
}

我将它传递给 int.ToString():

int number = 10;
Console.WriteLine(number.ToString(new MyFormatter()));

我得到的是:

GetFormat
10

虽然我希望得到的是:

GetFormat
Format
foo

编辑:我找到了How to create and use a custom IFormatProvider for DateTime?并且那里的答案说 DateTime.ToString() 除了 DateTimeFormatInfoCultureInfo 将不接受任何东西,如果对象不是这些类型,即使它实现了 ICustomFormatter - https://stackoverflow.com/a/2382481/492336 .

所以我的问题是,这是否适用于 ToString() 方法的所有情况?它是否也适用于 DataGridView,在哪些情况下我可以传递真正自定义的格式化程序?

最佳答案

当您对整数调用 ToString 并提供 IFormatProvider 时,它会尝试从中提取 NumberFormatInfo,大​​致按以下方式:

public static NumberFormatInfo GetInstance(IFormatProvider formatProvider)
{
  CultureInfo cultureInfo = formatProvider as CultureInfo;
  if (cultureInfo != null && !cultureInfo.m_isInherited)
    return cultureInfo.numInfo ?? cultureInfo.NumberFormat;
  NumberFormatInfo numberFormatInfo = formatProvider as NumberFormatInfo;
  if (numberFormatInfo != null)
    return numberFormatInfo;
  if (formatProvider != null)
  {
    NumberFormatInfo format = formatProvider.GetFormat(typeof (NumberFormatInfo)) as NumberFormatInfo;
    if (format != null)
      return format;
  }
  return NumberFormatInfo.CurrentInfo;
}

所以你看看是否所有其他方法都失败了,它调用类型等于 NumberFormatInfoGetFormat,并期望返回 NumberFormatInfo。您不会从 GetFormat 返回它,因此它使用默认格式化程序(当前 cutlure)。在这种情况下使用它的有效方法是这样的:

class MyFormatter : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(NumberFormatInfo)) {
            return new NumberFormatInfo()
            {
                // something here
            };
        }
        Console.WriteLine("GetFormat");
        return this;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        Console.WriteLine("Format");
        return "foo";
    }
}

但我怀疑您是否可以通过这种方式为任何数字返回任意值,例如“foo”。

关于c# - 尝试实现自定义格式化程序,但从未调用 ICustomFormatter.Format,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39871955/

相关文章:

c# - 如何在 DateTime.ParseExact 中使用 IFormatProvider

c# - 如何为 DateTime 创建和使用自定义 IFormatProvider?

c# - PowerBuilder 调用 C# 代码在某些计算机上崩溃?

c# - 使用 Linq to 对象,ToDictionary 方法不满足类型要求

c# - 是否可以将 C#11 'required' 修饰符用于 .NET Framework 4.8 和 .Net Standard 2.0?

c# - 如何在 Windows 窗体应用程序中获取 MP3 文件的 BPM 属性

c# - MVC 3 Html.DisplayFor(...) 代码不生成 HTML 代码