Pas pour ressusciter une vieille question, mais j'ai pensé que je pourrais proposer au moins une méthode un peu plus facile à utiliser, même si une configuration un peu plus compliquée.
Donc, si nous créons un nouveau formateur personnalisé, nous pouvons utiliser le formatage plus simple de string.Format
sans avoir à convertir notre numéro de téléphone en unlong
Commençons par créer le formateur personnalisé:
using System;
using System.Globalization;
using System.Text;
namespace System
{
/// <summary>
/// A formatter that will apply a format to a string of numeric values.
/// </summary>
/// <example>
/// The following example converts a string of numbers and inserts dashes between them.
/// <code>
/// public class Example
/// {
/// public static void Main()
/// {
/// string stringValue = "123456789";
///
/// Console.WriteLine(String.Format(new NumericStringFormatter(),
/// "{0} (formatted: {0:###-##-####})",stringValue));
/// }
/// }
/// // The example displays the following output:
/// // 123456789 (formatted: 123-45-6789)
/// </code>
/// </example>
public class NumericStringFormatter : IFormatProvider, ICustomFormatter
{
/// <summary>
/// Converts the value of a specified object to an equivalent string representation using specified format and
/// culture-specific formatting information.
/// </summary>
/// <param name="format">A format string containing formatting specifications.</param>
/// <param name="arg">An object to format.</param>
/// <param name="formatProvider">An object that supplies format information about the current instance.</param>
/// <returns>
/// The string representation of the value of <paramref name="arg" />, formatted as specified by
/// <paramref name="format" /> and <paramref name="formatProvider" />.
/// </returns>
/// <exception cref="System.NotImplementedException"></exception>
public string Format(string format, object arg, IFormatProvider formatProvider)
{
var strArg = arg as string;
// If the arg is not a string then determine if it can be handled by another formatter
if (strArg == null)
{
try
{
return HandleOtherFormats(format, arg);
}
catch (FormatException e)
{
throw new FormatException(string.Format("The format of '{0}' is invalid.", format), e);
}
}
// If the format is not set then determine if it can be handled by another formatter
if (string.IsNullOrEmpty(format))
{
try
{
return HandleOtherFormats(format, arg);
}
catch (FormatException e)
{
throw new FormatException(string.Format("The format of '{0}' is invalid.", format), e);
}
}
var sb = new StringBuilder();
var i = 0;
foreach (var c in format)
{
if (c == '#')
{
if (i < strArg.Length)
{
sb.Append(strArg[i]);
}
i++;
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
/// <summary>
/// Returns an object that provides formatting services for the specified type.
/// </summary>
/// <param name="formatType">An object that specifies the type of format object to return.</param>
/// <returns>
/// An instance of the object specified by <paramref name="formatType" />, if the
/// <see cref="T:System.IFormatProvider" /> implementation can supply that type of object; otherwise, null.
/// </returns>
public object GetFormat(Type formatType)
{
// Determine whether custom formatting object is requested.
return formatType == typeof(ICustomFormatter) ? this : null;
}
private string HandleOtherFormats(string format, object arg)
{
if (arg is IFormattable)
return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
else if (arg != null)
return arg.ToString();
else
return string.Empty;
}
}
}
Donc, si vous voulez utiliser ceci, vous feriez quelque chose comme ceci:
String.Format(new NumericStringFormatter(),"{0:###-###-####}", i["MyPhone"].ToString());
Quelques autres choses à penser:
À l'heure actuelle, si vous avez spécifié un formateur plus long qu'une chaîne pour formater, il ignorera simplement les signes # supplémentaires. Par exemple, cela String.Format(new NumericStringFormatter(),"{0:###-###-####}", "12345");
donnerait 123-45- donc vous voudrez peut-être qu'il prenne une sorte de caractère de remplissage possible dans le constructeur.
De plus, je n'ai pas fourni de moyen d'échapper au signe #, donc si vous vouliez l'inclure dans votre chaîne de sortie, vous ne seriez pas en mesure de le faire actuellement.
La raison pour laquelle je préfère cette méthode à Regex est que j'ai souvent des exigences pour permettre aux utilisateurs de spécifier le format eux-mêmes et il est considérablement plus facile pour moi d'expliquer comment utiliser ce format que d'essayer d'enseigner une expression régulière à un utilisateur.
De plus, le nom de la classe est un peu inapproprié car il fonctionne en fait pour formater n'importe quelle chaîne tant que vous voulez la garder dans le même ordre et simplement injecter des caractères à l'intérieur.