كيفية إنشاء واستخدام iformatprovider مخصص ل DateTime؟

StackOverflow https://stackoverflow.com/questions/2382154

  •  24-09-2019
  •  | 
  •  

سؤال

كنت أحاول إنشاء IFormatProvider التنفيذ الذي من شأنه أن يتعرف على سلاسل التنسيق المخصصة لكائنات DateTime. ها هو عملي:

 public class MyDateFormatProvider : IFormatProvider, ICustomFormatter
 {
  public object GetFormat(Type formatType)
  {
   if (formatType == typeof(ICustomFormatter))
   {
    return this;
   }
   return null;
  }

  public string Format(string format, object arg, IFormatProvider formatProvider)
  {
   if(arg == null) throw new ArgumentNullException("arg");
   if (arg.GetType() != typeof(DateTime)) return arg.ToString();
   DateTime date = (DateTime)arg;
   switch(format)
   {
    case "mycustomformat":
     switch(CultureInfo.CurrentCulture.Name)
     {
      case "en-GB":
       return date.ToString("ddd dd MMM");
      default:
       return date.ToString("ddd MMM dd");
     }
    default:
     throw new FormatException();
   }
  } 

كنت أتوقع أن أتمكن من استخدامه في DateTime.ToString(string format, IFormatProvider provider) طريقة مثل ذلك ، ولكن:

DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());

في هذا المثال ، الجري في الثقافة الأمريكية ، والنتيجة هي "00cu0Ao00or0aA", على ما يبدو لأن سلاسل تنسيق DateTime القياسية يتم تفسيرها.

ومع ذلك ، عندما أستخدم نفس الفصل بالطريقة التالية:

DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);

أحصل على ما أتوقعه ، أي "Sun Jan 02"

لا أفهم النتائج المختلفة. هل يمكن لأحد أن يشرح؟

شكرًا!

هل كانت مفيدة؟

المحلول

فحص DateTime.ToString الطريقة مع العاكس توضح أن DateTime الهيكل يستخدم DateTimeFormatInfo.GetInstance طريقة للحصول على المزود لاستخدامه في التنسيق. ال DateTimeFormatInfo.GetInstance يطلب تنسيق من النوع DateTimeFormatInfo من الموفر مرت ، أبدا ل ICustomFormmater, ، لذلك لا يعيد سوى مثيل أ DateTimeFormatInfo أو CultureInfo إذا لم يتم العثور على مزود. يبدو أن DateTime.ToString الطريقة لا تكرم ICustomFormatter واجهة مثل StringBuilder.Format الطريقة لا ، كما String.Format يظهر مثال.

أوافق على أن DateTime.ToString يجب أن تدعم الطريقة ICustomFormatter واجهة ، ولكن لا يبدو أنها حاليا. قد تغير كل هذا أو سيتغير في .NET 4.0.

نصائح أخرى

التفسير القصير هو أنه بينما

DateTime.ToString(string format, IFormatProvider provider)

يتيح لك تمرير أي شيء ينفذ IFormatProvider كواحدة من المعلمات ، فإنها في الواقع تدعم فقط نوعين محتملين تنفيذ IFormatProvider داخل الكود:

DateTimeFormatInfo أو CultureInfo

إذا كان لا يمكن إلقاء المعلمة الخاصة بك (باستخدام as) كلا أو تلك ، سوف تتخلف الطريقة إلى CurrentCulture.

String.Format لا يقتصر على هذه الحدود.

استخدم طريقة التمديد :)

public static class FormatProviderExtension
    {
        public static string FormatIt(string format, object arg, IFormatProvider formatProvider)
        {
            if (arg == null) throw new ArgumentNullException("arg");
            if (arg.GetType() != typeof(DateTime)) return arg.ToString();
            DateTime date = (DateTime)arg;
            switch (format)
            {
                case "mycustomformat":
                    switch (CultureInfo.CurrentCulture.Name)
                    {
                        case "en-GB":
                            return date.ToString("ddd dd MMM");
                        default:
                            return date.ToString("ddd MMM dd");
                    }
                default:
                    throw new FormatException();
            }
        }

        public static string ToString(this DateTime d, IFormatProvider formatProvider, string format)
        {
            return FormatIt(format, d, formatProvider);
        }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top