views:

1927

answers:

3

Hi there, I have my enumHelper class that contains these:

public static IList<T> GetValues()
{
  IList<T> list = new List<T>();
  foreach (object value in Enum.GetValues(typeof(T)))
  {
    list.Add((T)value);
  }
  return list;
}

and

public static string Description(Enum value)
{
  Attribute DescAttribute = LMIGHelper.GetAttribute(value, typeof(DescriptionAttribute));
  if (DescAttribute == null)
    return value.ToString();
  else
    return ((DescriptionAttribute)DescAttribute).Description;
}

my enum is something like:

public enum OutputType
{
 File,
 [Description("Data Table")]
 DataTable
}

So far so good. All the previous work fine. Now I want to add a new helper to return BindingList>, so I can link any enum to any combo using

BindingList<KeyValuePair<OutputType, string>> list = Enum<OutputType>.GetBindableList();
cbo.datasource=list;
cbo.DisplayMember="Value";
cbo.ValueMember="Key";

For that I added:

public static BindingList<KeyValuePair<T, string>> GetBindingList()
{
 BindingList<KeyValuePair<T, string>> list = new BindingList<KeyValuePair<T, string>>();
 foreach (T value in Enum<T>.GetValues())
 {
  string Desc = Enum<T>.Description(value);
  list.Add(new KeyValuePair<T, string>(value, Desc));
 }
 return list;
}

But "Enum.Description(value)" is not even compiling: Argument '1': cannot convert from 'T' to 'System.Enum'

How can I do that? Is that even possible?

Thank you.

A: 

Enum doesn't have a Description() method. The best you could do is have your enum implement an interface that has the Description() method. If you do that, then you can have

public static BindingList<KeyValuePair<T extends _interface_, String>> getBindingList()

and then inside of that you can refer to

T foo = ...?
foo.Description(...);
nsayer
+1  A: 

You should change:

public static string Description(Enum value)
{
  ...
}

to

public static string Description(T value)
{
   ...
}

so it accepts a value of the enumeration. Now here is where it gets tricky: you have a value, but attributes decorate the field which holds the value.

You actually need to reflect over the enumeration's fields and check the value of each against the value you've been given (results should be cached for performance):

foreach(var field in typeof(T).GetFields())
{
    T fieldValue;

    try
    {
        fieldValue = (T) field.GetRawConstantValue();
    }
    catch(InvalidOperationException)
    {
        // For some reason, one of the fields returned is {Int32 value__},
        // which throws an InvalidOperationException if you try and retrieve
        // its constant value.
        //
        // I am unsure how to check for this state before
        // attempting GetRawConstantValue().

        continue;
    }

    if(fieldValue == value)
    {
        var attribute = LMIGHelper.GetAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;

        return attribute == null ? value.ToString() : attribute.Description;
    }
}

Edit addressing the follow-up question

The FillComboFromEnum method is missing the type parameter for the enum. Try this:

public static void FillComboFromEnum<T>(ComboBox Cbo, BindingList<KeyValuePair<T, string>> List) where T : struct

Notice I constrained the type to be a struct. It's not a full enumeration constraint, but it's closer than nothing.

Bryan Watts
+2  A: 

Take a look at this article.

Scott Dorman