Azureはじめました

Windows Azureで業務システムを組んでみる日記

列挙型からSelectListItemを生成とか

列挙型プロパティのEditとかでDropdownを使いたいけどSelectListItemを毎回作るコードを書くのは面倒なのでユーティリティ化

  public static class ViewHelper {
        public static IEnumerable<SelectListItem> toList<T>() where T : struct, IConvertible {
            if (!typeof(T).IsEnum) {
                throw new ArgumentException("T must be an enumerated type");
            }
            List<SelectListItem> items = new List<SelectListItem>();
            foreach (var v in Enum.GetValues(typeof(T))) {
                items.Add( new SelectListItem(){Value=((int)v).ToString(),Text = Enum.GetName(typeof(T),v)} );
            }
            return items;
        }
}

usage

@Html.DropDownListFor(model => model.modelType, ViewHelper.toList<ModelClass.ModelType>(), new  { @class = "form-control" })

らくちん。

最初

        public static IEnumerable<SelectListItem> toList<T>() where T : Enum{

としてたんだけど、

Constraint cannot be special class 'System.Enum'.

と怒られた。どうやらEnumは型パラメータ制約では使えないらしい。

Since Enum Type implements IConvertible interface, a better implementation should be something like this:

public T GetEnumFromString<T>(string value) where T : struct, IConvertible {
    if (!typeof(T).IsEnum)     {
       throw new ArgumentException("T must be an enumerated type");
    }
     //... 
} 

This will still permit passing of value types implementing IConvertible. The chances are rare though.

c# - Create Generic method constraining T to an Enum - Stack Overflow

とのことで。

改良

毎回Listを使うのが非常にダサいのでLinqっぽく

public static IEnumerable<SelectListItem> toList<T>() where T : struct, IConvertible {
    if (!typeof(T).IsEnum) {
        throw new ArgumentException("T must be an enumerated type");
    }
    return Enum.GetValues(typeof(T)).OfType<IConvertible>()
           .Select(v => 
               new SelectListItem() { 
                   Value = v.ToInt32(System.Globalization.CultureInfo.CurrentCulture).ToString(), 
                   Text = Enum.GetName(typeof(T), v) 
               });
        }

Enum.GetValues()は非ジェネリックの配列が戻るのでOfTypeで''IConvertible''配列に変換。
((ここでTに変換しちゃうと、TにEnumの型制約が無いのでIntに変換できなくなる(の?)))
で、これをSelectで一気にSelectListItemにすると。