Domanda

I stava cercando di creare un'implementazione IFormatProvider che riconoscere stringhe di formato personalizzato per oggetti DateTime. Qui è la mia realizzazione:

 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();
   }
  } 

mi aspettavo di essere in grado di utilizzarlo nel metodo DateTime.ToString(string format, IFormatProvider provider) in questo modo, ma:

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

In questo esempio, l'esecuzione nella cultura degli Stati Uniti, il risultato è "00cu0Ao00or0aA", apparentemente perché le stringhe di formato DateTime standard, vengono interpretati.

Tuttavia, quando uso la stessa classe nel seguente modo:

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

ho capito quello che mi aspetto, vale a dire "Sun Jan 02"

Non capisco i diversi risultati. qualcuno potrebbe spiegare?

Grazie!

È stato utile?

Soluzione

Controllo tipo DateTime.ToString con spettacoli riflettenti che la struttura DateTime utilizza il metodo DateTimeFormatInfo.GetInstance per ottenere il provider da utilizzare per la formattazione. Il DateTimeFormatInfo.GetInstance richiede un formattatore di tipo DateTimeFormatInfo dal provider passata in, mai per ICustomFormmater, quindi restituisce solo un esempio di un DateTimeFormatInfo o CultureInfo se non viene trovato alcun provider. Sembra che il metodo DateTime.ToString non rispetta l'interfaccia ICustomFormatter come il metodo StringBuilder.Format fa, come i vostri String.Format esempio mostra.

Sono d'accordo che il metodo DateTime.ToString dovrebbe sostenere l'interfaccia ICustomFormatter, ma non sembra al momento. Tutto ciò può essere cambiata o cambierà in .NET 4.0.

Altri suggerimenti

La breve spiegazione è che, mentre

DateTime.ToString(string format, IFormatProvider provider)

consente di passare nulla attuazione IFormatProvider come uno dei suoi parametri, in realtà supporta solo 2 possibili tipi IFormatProvider attuazione al suo interno del codice:

DateTimeFormatInfo o CultureInfo

Se il parametro non può essere colato (usando as) sia come o di quelli, il metodo imposterà CurrentCulture.

String.Format non è limitata da tali limiti.

Utilizzare il metodo di estensione:)

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);
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top