【问题标题】:What does IFormatProvider do?IFormatProvider 做什么?
【发布时间】:2009-02-03 10:46:37
【问题描述】:

我在玩 Datetime.ParseExact 方法,它需要一个 IFormatProvider...

它可以输入null,但它到底是做什么的?

【问题讨论】:

标签: c# asp.net iformatprovider


【解决方案1】:

除了伊恩·博伊德的回答:

CultureInfo 也实现了这个接口,可以在你的情况下使用。例如,您可以解析法语日期字符串;你可以使用

var ci = new CultureInfo("fr-FR");
DateTime dt = DateTime.ParseExact(yourDateInputString, yourFormatString, ci);

【讨论】:

  • 在 .NET Framework 4.6 中似乎不再存在与您的示例匹配的重载。我相信您必须改用DateTime.ParseExact(string, string, IFormatProvider) - 因此:DateTime.ParseExact("20160409 111559","yyyyMMdd HHmmss",CultureInfo.CurrentCulture)
  • 在 .NET Framework 4.6.2 中没有您所指的输入参数。我只用了两个,效果很好DateTime dt = DateTime.Parse(yourDateInputString, ci);请修改你的答案。
  • 抱歉各位,我的回答迟迟没有更新。
【解决方案2】:

IFormatProvider 接口通常由CultureInfo 类为您实现,例如:

  • CultureInfo.CurrentCulture
  • CultureInfo.CurrentUICulture
  • CultureInfo.InvariantCulture
  • CultureInfo.CreateSpecificCulture("de-CA") //German (Canada)

接口是函数从文化中获取一组文化特定数据的网关。可以查询IFormatProvider 的两个常用区域性对象是:

它通常的工作方式是让IFormatProvider 给你一个DateTimeFormatInfo 对象:

DateTimeFormatInfo? format;
format = (DateTimeFormatInfo)provider.GetFormat(typeof(DateTimeFormatInfo));
if (format != null)
   DoStuffWithDatesOrTimes(format);

还有内幕消息是,任何IFormatProvider 接口都可能由继承自CultureInfo 或继承自DateTimeFormatInfo 的类实现,因此您可以直接转换接口:

CultureInfo? info = provider as CultureInfo;
if (info != null)
   format = info.DateTimeInfo;
else
{
   DateTimeFormatInfo? dtfi = provider as DateTimeFormatInfo;
   if (dtfi != null)
       format = dtfi;
   else
       format = (DateTimeFormatInfo)provider.GetFormat(typeof(DateTimeFormatInfo));
}

if (format != null)
   DoStuffWithDatesOrTimes(format);

但不要那样做

所有辛苦的工作都已经为你写好了:

IFormatProvider 获取DateTimeFormatInfo

DateTimeFormatInfo format = DateTimeFormatInfo.GetInstance(provider);

IFormatProvider 获取NumberFormatInfo

NumberFormatInfo format = NumberFormatInfo.GetInstance(provider);

IFormatProvider 的优点是您可以创建自己的文化对象。只要他们实现IFormatProvider,并返回他们要求的对象,你就可以绕过内置的文化。

您还可以使用IFormatProvider 传递任意文化对象 - 通过IFormatProvider。例如。不同文化中的上帝之名

  • 上帝
  • 耶和华
  • 耶和华
  • 耶和华神
  • אהיה אשר אהיה

这让您的自定义 LordsNameFormatInfo 类可以在 IFormatProvider 中运行,并且您可以保留成语。

实际上,您永远不需要自己调用IFormatProviderGetFormat 方法。

当您需要IFormatProvider 时,您可以传递CultureInfo 对象:

DateTime.Now.ToString(CultureInfo.CurrentCulture);

endTime.ToString(CultureInfo.InvariantCulture);

transactionID.toString(CultureInfo.CreateSpecificCulture("qps-ploc"));

注意:任何代码都会发布到公共领域。无需署名。

【讨论】:

    【解决方案3】:

    将 null 作为IFormatProvider 传递不是正确的方法。如果用户在其 PC 上具有自定义日期/时间格式,您将在解析和转换为字符串时遇到问题。我刚刚修复了一个错误,即有人在转换为字符串时将 null 作为 IFormatProvider 传递。

    您应该使用CultureInfo.InvariantCulture

    错误:

    string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", null);
    

    正确:

    string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", CultureInfo.InvariantCulture);
    

    【讨论】:

    • 我们有什么理由应该使用CultureInfo.InvariantCulture 而不是CultureInfo.CurrentCulture
    • InvariantCulture 是一种特殊的文化,它保证始终存在于任何机器上,并将始终转换并解析回相同的值。 CurrentCulture 是当前线程的文化。这可能会有所不同,如果您不使用相同的文化来转换为字符串并进行解析,则会出现格式错误...
    • @StephenBooher 传入null 将默认为CultureInfo.CurrentCulture。请参阅reference source 中的调用,如果您遵循调用链,null 最终会被 DateTimeFormatInfo.CurrentInfo 替换,这相当于 CultureInfo.CurrentCulture 输出的内容。
    • InvariantCulture 是我一直在寻找的。谢谢
    【解决方案4】:

    IFormatProvider 为相关方法提供文化信息。 DateTimeFormatInfo 实现 IFormatProvider,并允许您指定希望日期/时间显示的格式。示例可以在相关 MSDN 页面上找到。

    【讨论】:

      【解决方案5】:

      你可以在这里看到http://msdn.microsoft.com/en-us/library/system.iformatprovider.aspx

      请参阅那里的备注和示例部分。

      【讨论】:

      • 讽刺的是IFormatProvider 的示例代码没有使用IFormatProvider
      【解决方案6】:
      【解决方案7】:

      MSDN

      .NET Framework 包括以下三个预定义的 IFormatProvider 实现,以提供用于格式化或解析数字和日期和时间值的文化特定信息:

      1. NumberFormatInfo 类,它提供用于格式化数字的信息,例如特定文化的货币、千位分隔符和小数分隔符符号。有关由 NumberFormatInfo 对象识别并用于数字格式化操作的预定义格式字符串的信息,请参阅标准数字格式字符串和自定义数字格式字符串。
      2. DateTimeFormatInfo 类,它提供用于格式化日期和时间的信息,例如特定文化的日期和时间分隔符或日期的年、月和日组件的顺序和格式。有关由 DateTimeFormatInfo 对象识别并用于数字格式化操作的预定义格式字符串的信息,请参阅标准日期和时间格式字符串和自定义日期和时间格式字符串。
      3. CultureInfo 类,代表特定的文化。它的GetFormat 方法返回特定于文化的NumberFormatInfoDateTimeFormatInfo 对象,具体取决于CultureInfo 对象是否用于涉及数字或日期和时间的格式化或解析操作。

      .NET Framework 还支持自定义格式。这通常涉及创建实现 IFormatProvider 和 ICustomFormatter 的格式化类。然后将此类的一个实例作为参数传递给执行自定义格式化操作的方法,例如String.Format(IFormatProvider, String, Object[])

      【讨论】:

        【解决方案8】:

        DateTimeFormatInfo 类实现了这个接口,因此它允许您控制 DateTime 字符串的格式。

        【讨论】:

          【解决方案9】:

          该问题涉及 IFormatProvider 和 DateTime,但您也可以在 .NET 的其他上下文中使用 IFormatProvider,例如用于 string.Format。

          然后你传入 IFormatProvider 实例,你可以通过实现 IFormatProvider 来指定如何为对象格式化字符串。因此,IFormatProvider 和相关的 ICustomFormatter 接口在 .NET 中的使用范围更广,而不仅仅是日期。

          例如考虑这个实现:

          using System;
          
          namespace ConsoleApp
          {
              class EmployeeProductivityFormatProvider : IFormatProvider, ICustomFormatter
              {
                  public string Format(string format, object arg, IFormatProvider formatProvider)
                  {
                      int rating = (int)arg;
          
                      if (rating == 0)
                      {
                          return $"{rating} (new employee)";
                      }
          
                      if (rating > 0)
                      {
                          return $"{rating} (good employee)";
                      }
          
                      return $"{rating} (bad employee)";
                  }
          
                  public object GetFormat(Type formatType)
                  {
                      if (formatType == typeof(ICustomFormatter))
                      {
                          return this;
                      }
          
                      return null;
                  }
              }
          }
          

          现在我们可以通过指定这样的 int 值来获取员工的字符串表示形式:

              string prod = string.Format(new EmployeeProductivityFormatProvider(),
                                          "Productivity rating: {0}",
                                          employee.ProductivityRating);
          

          说到 DateTime,有很多已经创建好的 IFormatProvider 实现可供选择。这是将对象表示为字符串并在 .NET 中指定其格式的一种非常灵活的方式,是一个非常笼统的概念。

          【讨论】:

          • 正是我正在寻找的实现。我正在尝试构建一个类型映射器管道。你的回答帮助我解决了最后一个难题。 Source Type -> Primitive Type Conversion(现在使用 Func )->Type-Constraint Identification(使用谓词)-> Type Formatter Application(使用 IFormatProvider 和 iCustomFormatter)-> Target Type。我梦想有一天电脑可以自动投射类型。
          猜你喜欢
          • 2011-11-23
          • 2012-08-14
          • 2014-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-20
          • 1970-01-01
          • 2011-08-23
          相关资源
          最近更新 更多