5

我试图弄清楚 IFormatProvider 和 ICustomFormatter在 DataGridView 列中的 Format TimeSpan 如何在 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()));

我得到的是:

获取格式
10

虽然我希望得到的是:

获取格式
格式
富

编辑:我发现如何为 DateTime 创建和使用自定义 IFormatProvider?并且那里的答案说除了或DateTime.ToString()之外什么都不会接受,如果一个对象不是这些类型,即使它实现了,它也会被拒绝- https://stackoverflow.com/a/2382481/492336DateTimeFormatInfoCultureInfoICustomFormatter

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

4

2 回答 2

1

当你在 integer 上调用 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;
}

因此,您会看到是否所有其他方法都失败了,它会GetFormat以等于 的类型调用NumberFormatInfo,并期望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”。

于 2016-10-05T10:58:43.423 回答
-2

实际上 ToString() 函数接受 IFormatProvider 作为其签名的参数:

ToString(IFormatProvider)
ToString(String)
ToString(String,IFormatProvider)

而 IFormatProvider 只有GetFormat(Type)实现的功能。ToString()不使用ICustomFormatter哪个有Format()功能。所以实现IFormatProvider是:

class MyFormatter : IFormatProvider
    {
        public object GetFormat(Type formatType)
        {
            Console.WriteLine("GetFormat");
            return this;
        }    
    }
于 2016-10-05T11:00:20.967 回答