2012-03-26 33 views
4

我的代码如下两行:的String.Format VS int.ToString的问候iCustomFormatter问题

var BadResult = (100).ToString("B", new CustomFormatter()); 
var GoodResult = String.Format("{0}", 100, new CustomFormatter()); 

然而,BadResult显然是坏的,GoodResult好。我的CustomFormatter类被声明如下:(同样,与一个功能我觉得是相关的):

public class CustomFormatter 
       : IFormatProvider, ICustomFormatter 
{ 
    public virtual Object GetFormat(Type formatType) 
    { 
     String formatTypeName = formatType.ToString(); 
     formatTypeName = formatTypeName; 
     Object formatter = null; 
     if (formatType == typeof(ICustomFormatter)) 
      formatter = this; 
     return formatter; 
    } 
} 

问题本身,当我运行的代码以“好的结果”行了,的getFormat功能requestng CustomFormatter的一个实例。

每当使用Float.Tostring()调用它时,它的期望NumberFormatInfo的一个实例。

我最初跳到“我的CustomFormatter应该从NumberFormatInfo派生”。不幸的是,这个班是封闭的。

因此:我需要做什么才能用自定义格式化程序调用Float.ToString()?

谢谢!

回答

1

我不确定你可以使用Number.ToString的自定义格式化程序。我用自定义格式化程序看到的所有示例都使用String.Format(例如this on the MSDN)。

我建议你尝试扩展方法:

public static class MyExt 
{ 
    public static string ToFormattedString(this float This, string format, IFormatProvider provider) 
    { 
     return String.Format(provider,"{0}", new object[] {This}); 
    } 
} 

//now this works 
var NoLongerBadResult = (100F).ToFormattedString("B", new CustomFormatter()); 

编辑好吧,我想我得到了它。你需要从的getFormat改变当前的NumberFormatInfo并返回它:

public class CustomFormatter : IFormatProvider, ICustomFormatter 
{ 
    public object GetFormat(Type formatType) 
    { 
     if (formatType == typeof(ICustomFormatter)) 
      return this; 
     else if(formatType == typeof(NumberFormatInfo)) 
     { 
      NumberFormatInfo nfi = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); // create a copy of the current NumberFormatInfo 
      nfi.CurrencySymbol = "Foo"; // change the currency symbol to "Foo" (for instance) 
      return nfi; // and return our clone 
     } 
     else 
      return null; 
    } 

    public string Format(string fmt, object arg, IFormatProvider formatProvider) 
    { 
     return "test"; 
    } 
} 

现在这个工程:

var NowItWorks = (100).ToString("C", new CustomFormatter()); 
var GoodResult = String.Format(new CustomFormatter(),"{0}", 100); 
Console.WriteLine(NowItWorks); // Foo 100.00 
Console.WriteLine(GoodResult); // test 
+0

从我的互联网侦探工作中,这似乎开始看起来像解决方案。然而,为什么地狱是一个float.tostring()重载,允许你给一个icustomformatter? – greggorob64 2012-03-26 14:31:32

+0

@ greggorob64你是对的,它应该是可能的。 [Single.ToString](http://msdn.microsoft.com/en-us/library/6dx8etks.aspx)的文档说“提供者参数是一个IFormatProvider实现,它的GetFormat方法返回一个NumberFormatInfo对象”,所以它看起来应该有一种方法来创建一个NumberFormatInfo对象并从您的自定义getformat中返回它。尽管...我还没有找到办法做到这一点但我仍然在尝试 – 2012-03-26 14:43:26

+1

@ greggorob64 ok,所以...您的自定义提供程序工作正常,但是如果您将其与Number.Tostring一起使用,您只能使用NumberFormatProvider可以理解的格式,因此B不起作用(但如果您尝试'(100).ToString(“C”,新的CustomFormatter());'它的工作原理和100被格式化为货币)。例如,您可能会返回一个自定义的NumberFormatProvider,您可以在其中更改小数点的符号,但是您只能使用NumberFormatInfo自身允许您自定义的更改类型 – 2012-03-26 14:52:38

2

var GoodResult = String.Format("{0}", 100, new CustomFormatter()); 

未使用的CustomFormatter。所以你的好结果似乎是通过默认来实现的。

你想要的可能是:

var GoodResult = String.Format(new CustomFormatter(), "{0}", 100); 

见是如何工作的。

+0

也许我问我的问题糟糕,我想BadResult工作。 – greggorob64 2012-03-26 14:01:40

+0

我需要(100.0).ToString(“{0}”,new CustomFormatter());上班。我有String.Format已经正常工作。 – greggorob64 2012-03-26 14:07:32

+0

这是不可能的。它采用IFormatProvider的唯一原因是允许传递CultureInfo。无论如何,它使用CultureInfo内部的NumberFormatInfo。所以唯一的Int.ToString类型可以接受的是NumberFormatInfo。 – Will 2012-03-26 14:22:48