1

We have some stuff that may be exported into various formats. Currently we have these formats represented by an enum like this:

[Flags]
public enum ExportFormat
{
    None = 0x0,
    Csv = 0x1,
    Tsv = 0x2,
    Excel = 0x4,
    All = Excel | Csv | Tsv
}

Problem is that these must be enumerated and they also need a translation or description in the ui. Currently I solved this by creating two extension methods. They work, but I don't really like them or the solution at all... they feel kind of smelly. Problem is I don't really know how I could do this better. Does anyone have any good alternatives? These are the two methods:

    public static IEnumerable<ExportFormat> Formats(this ExportFormat exportFormats)
    {
        foreach (ExportFormat e in Enum.GetValues(typeof (ExportFormat)))
        {
            if (e == ExportFormat.None || e == ExportFormat.All)
                continue;

            if ((exportFormats & e) == e)
                yield return e;
        }
    }

    public static string Describe(this ExportFormat e)
    {
        var r = new List<string>();

        if ((e & ExportFormat.Csv) == ExportFormat.Csv)
            r.Add("Comma Separated Values");

        if ((e & ExportFormat.Tsv) == ExportFormat.Tsv)
            r.Add("Tab Separated Values");

        if ((e & ExportFormat.Excel) == ExportFormat.Excel)
            r.Add("Microsoft Excel 2007");

        return r.Join(", ");
    }

Maybe this is the way to do this, but I have a feeling there must be better ways to do it. How could I refactor this?

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Svish
  • 152,914
  • 173
  • 462
  • 620
  • Don't you have to localize those strings as well? If so, they would be in resource files anyway, so there's no point in placing them _anywhere_ in the code. – Pavel Minaev Jul 09 '09 at 08:54
  • True. But would still need some way of connecting the resource key with the enum. – Svish Jul 09 '09 at 09:28

3 Answers3

5

You could use the Formats method inside Describe to avoid doing all the bit operations at multiple places, like this:

private static Dictionary<ExportFormat, string> FormatDescriptions =
    new Dictionary<ExportFormat,string>()
{
    { ExportFormat.Csv, "Comma Separated Values" },
    { ExportFormat.Tsv, "Tab Separated Values" },
    { ExportFormat.Excel, "Microsoft Excel 2007" },            
};

public static string Describe(this ExportFormat e)
{
    var formats = e.Formats();
    var descriptions = formats.Select(fmt => FormatDescriptions[fmt]);

    return string.Join(", ", descriptions.ToArray());
}

This way, it is easy to incorporate the string descriptions from an external source or localization, as hinted above.

Timbo
  • 27,472
  • 11
  • 50
  • 75
1

The only other way comes to my mind is the usage of the System.Attribute class.

public class FormatDescription : Attribute
{
    public string Description { get; private set; }

    public FormatDescription(string description)
    {
        Description = description;
    }
}

And then use Reflection with in your Describe function. The only benefit of this method would be to have definition and the description at one place.

ba__friend
  • 5,783
  • 2
  • 27
  • 20
  • You might want to cache the lookups at runtime as they will not change and it would be costly to use reflection for repeated calls to Describe. – adrianbanks Jul 09 '09 at 09:11
  • This would be difficult to localize though, wouldn't it? Since as far as I know you can't really look up resource strings etc. when using attributes.. – Svish Jul 09 '09 at 09:30
0

Dupe: How do I have an enum bound combobox with custom string formatting for enum values?

You could write an TypeConverter that reads specified attributes to look them up in your resources. Thus you would get multi-language support for display names without much hastle.

Look into the TypeConverter's ConvertFrom/ConvertTo methods, and use reflection to read attributes on your enum fields.

Addition:

Scroll down in the linked post for a implementation of a TypeConverter that does part of what is required for full support.

This would support an application where you have several languages at the same time, not only code name -> english name.

Remember that this is only the display name, never the stored value. You should always store the code name, or the integer value, to support users with different locales using the same data.

Community
  • 1
  • 1
sisve
  • 19,501
  • 3
  • 53
  • 95
  • Nice catch on the related question (dupe, I don't know), but I tend to agree with the higer rated answers to that question. If you make a custom TypeConverter, then you effectively change how that enum gets represented as a string, potentially effecting things like serialization, right? I do like the GetDescription and NicenessComboBoxItem ideas. – Paul Hooper Jul 13 '09 at 21:26