Je me rends compte maintenant que vous étiez en train de demander à quelque chose qui pourrait fonctionner avec de la Ficelle.Format() - je suppose que je devrais avoir lu la question deux fois avant de poster ;-)
Je n'aime pas la solution où vous avez à transmettre explicitement dans un format fournisseur de tous les temps - de ce que j'ai pu recueillir à partir de cet article, la meilleure façon d'aborder cette, est de mettre en place un Fichier de type, la mise en œuvre de la IFormattable interface.
Je suis allé de l'avant et mis en place une structure qui prend en charge cette interface, et qui peut être coulé à partir d'un entier. Dans mon propre fichier Api, je vais avoir mon .La taille du fichier de propriétés retour d'une Taille de l'instance.
Voici le code:
using System.Globalization;
public struct FileSize : IFormattable
{
private ulong _value;
private const int DEFAULT_PRECISION = 2;
private static IList<string> Units;
static FileSize()
{
Units = new List<string>(){
"B", "KB", "MB", "GB", "TB"
};
}
public FileSize(ulong value)
{
_value = value;
}
public static explicit operator FileSize(ulong value)
{
return new FileSize(value);
}
override public string ToString()
{
return ToString(null, null);
}
public string ToString(string format)
{
return ToString(format, null);
}
public string ToString(string format, IFormatProvider formatProvider)
{
int precision;
if (String.IsNullOrEmpty(format))
return ToString(DEFAULT_PRECISION);
else if (int.TryParse(format, out precision))
return ToString(precision);
else
return _value.ToString(format, formatProvider);
}
/// <summary>
/// Formats the FileSize using the given number of decimals.
/// </summary>
public string ToString(int precision)
{
double pow = Math.Floor((_value > 0 ? Math.Log(_value) : 0) / Math.Log(1024));
pow = Math.Min(pow, Units.Count - 1);
double value = (double)_value / Math.Pow(1024, pow);
return value.ToString(pow == 0 ? "F0" : "F" + precision.ToString()) + " " + Units[(int)pow];
}
}
Et un Test Unitaire simple qui montre comment cela fonctionne:
[Test]
public void CanUseFileSizeFormatProvider()
{
Assert.AreEqual(String.Format("{0}", (FileSize)128), "128 B");
Assert.AreEqual(String.Format("{0}", (FileSize)1024), "1.00 KB");
Assert.AreEqual(String.Format("{0:0}", (FileSize)10240), "10 KB");
Assert.AreEqual(String.Format("{0:1}", (FileSize)102400), "100.0 KB");
Assert.AreEqual(String.Format("{0}", (FileSize)1048576), "1.00 MB");
Assert.AreEqual(String.Format("{0:D}", (FileSize)123456), "123456");
// You can also manually invoke ToString(), optionally with the precision specified as an integer:
Assert.AreEqual(((FileSize)111111).ToString(2), "108.51 KB");
}
Comme vous pouvez le voir, la Taille du fichier de type peut maintenant être correctement mis en forme, et il est également possible de spécifier le nombre de décimales, ainsi que l'application régulière de mise en forme numérique si nécessaire.
Je suppose que vous pourriez prendre ce beaucoup plus loin, par exemple en autorisant explicite de sélection de format, par exemple "{0:KO}" pour forcer le formatage en kilo-octets. Mais je vais vous laisser à présent.
Je suis aussi en laissant mon post initial ci-dessous pour les deux préférez ne pas utiliser la mise en forme de l'API...
100 façons à la peau d'un chat, mais voici mon approche - ajout d'une méthode d'extension pour le type int:
public static class IntToBytesExtension
{
private const int PRECISION = 2;
private static IList<string> Units;
static IntToBytesExtension()
{
Units = new List<string>(){
"B", "KB", "MB", "GB", "TB"
};
}
/// <summary>
/// Formats the value as a filesize in bytes (KB, MB, etc.)
/// </summary>
/// <param name="bytes">This value.</param>
/// <returns>Filesize and quantifier formatted as a string.</returns>
public static string ToBytes(this int bytes)
{
double pow = Math.Floor((bytes>0 ? Math.Log(bytes) : 0) / Math.Log(1024));
pow = Math.Min(pow, Units.Count-1);
double value = (double)bytes / Math.Pow(1024, pow);
return value.ToString(pow==0 ? "F0" : "F" + PRECISION.ToString()) + " " + Units[(int)pow];
}
}
Avec cette extension dans votre assemblée, pour le format d'un fichier, il suffit d'utiliser un énoncé comme (1234567).ToBytes()
La suite MbUnit test clarifie précisément à quoi ressemble la sortie:
[Test]
public void CanFormatFileSizes()
{
Assert.AreEqual("128 B", (128).ToBytes());
Assert.AreEqual("1.00 KB", (1024).ToBytes());
Assert.AreEqual("10.00 KB", (10240).ToBytes());
Assert.AreEqual("100.00 KB", (102400).ToBytes());
Assert.AreEqual("1.00 MB", (1048576).ToBytes());
}
Et vous pouvez facilement changer les unités et la précision de ce qui convient à vos besoins :-)