简体   繁体   English

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

[英]Trying to implement a custom formatter but ICustomFormatter.Format is never called

I'm trying to figure out how IFormatProvider and ICustomFormatter work after following Format TimeSpan in DataGridView column on how to customize a TimeSpan in a DataGridView. 我试图弄清楚IFormatProvider和ICustomFormatter 在DataGridView列中关于如何在DataGridView中自定义TimeSpan之后如何工作。 I've created a completely custom formatter that always returns "foo" regardless of what it is formatting. 我创建了一个完全自定义的格式化程序,无论格式化的是什么,它始终返回“foo”。

I'm using it on Int but I assume it should work on all types as it doesn't check the value being passed, it just returns "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";
    }
}

And I'm passing it to int.ToString() : 我将它传递给int.ToString()

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

What I'm getting is: 我得到的是:

GetFormat
10

While what I was hoping to get is: 虽然我希望得到的是:

GetFormat
Format
foo

Edit: I found How to create and use a custom IFormatProvider for DateTime? 编辑:我发现如何为DateTime创建和使用自定义IFormatProvider? and the answers there say that DateTime.ToString() will not accept anything but DateTimeFormatInfo or CultureInfo and an object will be rejected if it's not of these types even if it implements ICustomFormatter - https://stackoverflow.com/a/2382481/492336 . 那里的答案说DateTime.ToString()除了DateTimeFormatInfoCultureInfo不会接受任何东西,如果它不是这些类型的对象将被拒绝,即使它实现了ICustomFormatter - https://stackoverflow.com/a/2382481/492336

So my question is then does that hold in all cases of the ToString() methods? 那么我的问题就是在ToString()方法的所有情况下都适用吗? Does it hold also for DataGridView, and in which cases can I pass a truly custom formatter? 它是否也适用于DataGridView,在哪些情况下我可以传递真正的自定义格式化程序?

When you call ToString on integer and provide IFormatProvider, it will try to extract NumberFormatInfo from it, roughly in the following way: 当你在整数上调用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;
}

So you see if all else fails, it calls GetFormat with type equal to NumberFormatInfo , and expects NumberFormatInfo back. 所以你看看是否所有其他方法都失败了,它调用类型等于NumberFormatInfo GetFormat ,并期望返回NumberFormatInfo You don't return it from GetFormat , so it uses default formatter instead (current cutlure). 您不从GetFormat返回它,因此它使用默认格式化程序(current cutlure)。 So valid way to use it in this case would be something like: 在这种情况下使用它的有效方法是:

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";
    }
}

But this way I doubt you can return arbitrary values like "foo" for any number. 但是这样我怀疑你可以为任何数字返回像“foo”这样的任意值。

Actually ToString() function accept IFormatProvider as an argument its signature says: 实际上ToString()函数接受IFormatProvider作为参数,其签名如下:

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

and IFormatProvider only has GetFormat(Type) function to implement. 而IFormatProvider只有GetFormat(Type)函数才能实现。 ToString() doesnt use ICustomFormatter which is having Format() function. ToString()不使用具有Format()函数的ICustomFormatter So the implementation for IFormatProvider is : 所以IFormatProvider的实现是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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