2013-08-09 15 views
5

私のプロジェクトでEnumからSelectListを作成する必要があります。一般的な列挙型から選択リストへの拡張方法

私は以下の特定の列挙型から選択リストを作成するコードを持っていますが、ANY列挙型の拡張メソッドを作成したいと思います。この例では、各列挙値this postを参照

var list = new SelectList(
      Enum.GetValues(typeof(eChargeType)) 
      .Cast<eChargeType>() 
      .Select(n => new 
       { 
        id = (int)n, 
        label = n.ToString() 
       }), "id", "label", charge.type_id); 

DescriptionAttributeの値を取得し、どのように私は進むのか?

public static void ToSelectList(this Enum e) 
{ 
    // code here 
} 

答えて

4

あなたが苦労していると思うのは、説明の取得です。一度あなたがあなたの正確な結果を与える最終的な方法を定義できるものを持っていると確信しています。

最初に、拡張メソッドを定義すると、enum型自体ではなく、列挙型の値に対して機能します。そして、私は使い方が簡単なので、(静的メソッドのような)型のメソッドを呼びたいと思います。残念ながら、それらを定義することはできません。

できることは次のとおりです。 、

public static string GetDescription(this Enum value) { 
    string description = value.ToString(); 
    FieldInfo fieldInfo = value.GetType().GetField(description); 
    DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 

    if (attributes != null && attributes.Length > 0) { 
     description = attributes[0].Description; 
    } 
    return description; 
} 

次の列挙型のすべての値をとる方法を定義し、我々値をルックアップするために、以前のメソッドを使用します。まず、それが1つを持っている場合は、列挙値の説明を取得するメソッドを定義します表示したい、そしてそのリストを返す。ジェネリック引数は推論できます。

public static List<KeyValuePair<TEnum, string>> ToEnumDescriptionsList<TEnum>(this TEnum value) { 
    return Enum 
     .GetValues(typeof(TEnum)) 
     .Cast<TEnum>() 
     .Select(x => new KeyValuePair<TEnum, string>(x, ((Enum)((object)x)).GetDescription())) 
     .ToList(); 
} 

最後に、使いやすさのために、値なしで直接呼び出す方法です。しかし、汎用の引数はオプションではありません。

public static List<KeyValuePair<TEnum, string>> ToEnumDescriptionsList<TEnum>() { 
    return ToEnumDescriptionsList<TEnum>(default(TEnum)); 
} 

今、私たちはこのようにそれを使用することができます:

enum TestEnum { 
    [Description("My first value")] 
    Value1, 
    Value2, 
    [Description("Last one")] 
    Value99 
} 

var items = default(TestEnum).ToEnumDescriptionsList(); 
// or: TestEnum.Value1.ToEnumDescriptionsList(); 
// Alternative: EnumExtensions.ToEnumDescriptionsList<TestEnum>() 
foreach (var item in items) { 
    Console.WriteLine("{0} - {1}", item.Key, item.Value); 
} 
Console.ReadLine(); 

出力する:相手に後期

Value1 - My first value 
Value2 - Value2 
Value99 - Last one 
+0

ありがとう: )正直言って、私はちょうど(もし可能であれば)本当に簡単なものを望んでいるので、 'eChargeType.ToSelectList()'を使うことができます - 私は不要な混乱を追加する可能性がある 'DescriptionAttribute'を除外するために私の例の複雑さを減らしました。ありがとう! – Jimbo

+0

残念ながら、静的メソッドを列挙型に追加したいので、 'eChargeType.ToSelectList()'は不可能です。それは不可能ですが、どこかで静的ヘルパーメソッドを作成することができます。 – Maarten

+0

上記のあなたのコメントを参照して、この投稿の作者が達成したいと思っていたことについて、どんな光を放つことができますか? http://stackoverflow.com/a/276589/175893私は同じ任務にいると思っていました!ありがとう – Jimbo

1

、しかしそこには受け入れ答えではありません、それは他の人を助ける可能性があるため。

@Maartenが述べたように、拡張メソッドはenum型itelfではなくenumの値に作用しますあなたは

public static class EnumHelper 
{ 
    public static SelectList GetSelectList<T>(string selectedValue, bool useNumeric = false) 
    { 
     Type enumType = GetBaseType(typeof(T)); 

     if (enumType.IsEnum) 
     { 
      var list = new List<SelectListItem>(); 

      // Add empty option 
      list.Add(new SelectListItem { Value = string.Empty, Text = string.Empty }); 

      foreach (Enum e in Enum.GetValues(enumType)) 
      { 
       list.Add(new SelectListItem { Value = useNumeric ? Convert.ToInt32(e).ToString() : e.ToString(), Text = e.Description() }); 
      } 

      return new SelectList(list, "Value", "Text", selectedValue); 
     } 

     return null; 
    } 

    private static bool IsTypeNullable(Type type) 
    { 
     return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)); 
    } 

    private static Type GetBaseType(Type type) 
    { 
     return IsTypeNullable(type) ? type.GetGenericArguments()[0] : type; 
    } 

:Maarteenのsoultionであなたは、しかし、あなたはちょうどそうのような静的ヘルパーメソッドを使用する方が簡単であることを、私が行ったように、見つけることが、上の拡張メソッドを呼び出すためにダミーまたはデフォルト値を作成することができます

viewModel.ProvinceSelect = EnumHelper.GetSelectList<Province>(model.Province); 

または文字列の代わりにオプションの数値使用:

viewModel.MonthSelect = EnumHelper.GetSelectList<Month>(model.Month,true); 

を私はからもらったこのための基本的な考え方このような選択リストを作成します0、私は私のニーズに合わせてそれを変更しましたが。私が追加したことの1つは、値にintをオプションとして使用できることでした。私はまた、thisブログの記事に基づいて説明属性を取得するために、列挙型の拡張機能を追加しました:

public static class EnumExtensions 
{ 
    public static string Description(this Enum en) 
    { 
     Type type = en.GetType(); 

     MemberInfo[] memInfo = type.GetMember(en.ToString()); 

     if (memInfo != null && memInfo.Length > 0) 
     { 
      object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); 

      if (attrs != null && attrs.Length > 0) 
      { 
       return ((DescriptionAttribute)attrs[0]).Description; 
      } 
     } 

     return en.ToString(); 
    }  
} 
0

列挙型は、コレクション全体に固定拡張子を持つことができないので、列挙型のベースクラスを拡張するための便利な方法がです静的型付きクラス。

次のコードを使用して達成することができ
Enum<MyCustomEnumType>.GetSelectItems(); 

:列挙型は、共有インターフェイスタイプの悪用が可能である必要はありませんが、クラス名の列挙が必要があるため

public static class Enum<T> 
{ 
    public static SelectListItem[] GetSelectItems() 
    { 
     Type type = typeof(T); 
     return 
      Enum.GetValues(type) 
       .Cast<object>() 
       .Select(v => new SelectListItem() { Value = v.ToString(), Text = Enum.GetName(type, v) }) 
       .ToArray(); 
    } 
} 

これは、次のような簡潔なコードを許可します混乱を払拭する。ここで

0

を修正[intにタイプキャスト値]で、簡略化され、[代わりのgetNameのtoStringオーバーライドを使用しています]の代わりに、配列のリストを返すNathaniels答えのバージョン:詳細な応答のための

public static class Enum<T> 
{ 
    //usage: var lst = Enum<myenum>.GetSelectList(); 
    public static List<SelectListItem> GetSelectList() 
    { 
     return Enum.GetValues(typeof(T)) 
       .Cast<object>() 
       .Select(i => new SelectListItem() 
          { Value = ((int)i).ToString() 
           ,Text = i.ToString() }) 
       .ToList(); 
    } 

} 
関連する問題