Dop il ICustomFromatter per scrivere numeri in lettere, ecco un’altro FormatProvider per scrivere un numero intero da cifre arabe in cifre romane:
public class RomanFormatProvider : IFormatProvider, ICustomFormatter
{
IFormatProvider _parent;
public RomanFormatProvider() : this(CultureInfo.CurrentCulture) { }
public RomanFormatProvider(IFormatProvider parent)
{
_parent = parent;
}
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter)) return this;
return null;
}
public string Format(string format, object arg, IFormatProvider prov)
{
if (arg == null || format != "RO")
return string.Format(_parent, "{0:" + format + "}", arg);
return ToRoman(arg.ToString());
}
private string ToRoman(string n)
{
StringBuilder r = new StringBuilder();
int i = 0;
foreach (var c in n)
{
r.Append(calcDigit(int.Parse(c.ToString()), n.Length - i - 1));
i++;
}
return r.ToString();
}
class Level
{
public Level(string i, string v, string x)
{
this.i = i;
this.v = v;
this.x = x;
}
public string i { get; set; }
public string v { get; set; }
public string x { get; set; }
}
static Level[] levels = new RomanFormatProvider.Level[] {
new Level("I", "V", "X"),
new Level("X", "L", "C"),
new Level("C", "D", "M")
};
string calcDigit(int d, int l)
{
string str;
if (l > 2)
{
str = "";
for (var k = 1; k <= d * Math.Pow (10, l - 3); k++)
str += "M";
return str;
}
else
switch (d)
{
case 1:
return levels[l].i;
case 2:
return levels[l].i + levels[l].i;
case 3:
return levels[l].i + levels[l].i + levels[l].i;
case 4:
return levels[l].i + levels[l].v;
case 5:
return levels[l].v;
case 6:
return levels[l].v + levels[l].i;
case 7:
return levels[l].v + levels[l].i + levels[l].i;
case 8:
return levels[l].v + levels[l].i + levels[l].i + levels[l].i;
case 9:
return levels[l].i + levels[l].x;
default:
return "";
}
}
}
Con questo CustomFormatter è possibile scrivere semplicemente:
RomanFormatProvider fr = new RomanFormatProvider();
s = string.Format(fr, "Il numero {0} in lettere è {0:RO}", 1971);
Console.WriteLine(s);
Il cui output è:
Il numero 1971 in lettere è MCMLXXI