Não para ressuscitar uma pergunta antiga, mas achei que eu poderia oferecer pelo menos um método um pouco mais fácil de usar, se um pouco mais complicado de uma configuração.
Portanto, se criarmos um novo formatador personalizado, podemos usar a formatação mais simples de string.Format
sem precisar converter nosso número de telefone em umlong
Então, primeiro vamos criar o formatador personalizado:
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;
}
}
}
Então, se você quiser usar isso, faça algo assim:
String.Format(new NumericStringFormatter(),"{0:###-###-####}", i["MyPhone"].ToString());
Algumas outras coisas em que pensar:
No momento, se você especificou um formatador mais longo do que uma string para formatar, apenas ignorará os sinais # adicionais. Por exemplo, issoString.Format(new NumericStringFormatter(),"{0:###-###-####}", "12345");
resultaria em 123-45-, portanto, convém que ele exija algum tipo de caractere de preenchimento possível no construtor.
Também não forneci uma maneira de escapar de um sinal de #, portanto, se você quisesse incluir isso em sua string de saída, não seria capaz de como está agora.
A razão de eu preferir esse método ao Regex é que geralmente tenho requisitos para permitir que os usuários especifiquem o formato eles mesmos e é consideravelmente mais fácil explicar como usar esse formato do que tentar ensinar um regex para o usuário.
Além disso, o nome da classe é um pouco inadequado, uma vez que realmente funciona para formatar qualquer sequência, desde que você queira mantê-la na mesma ordem e injetar caracteres dentro dela.