2014-12-11 5 views
0

У меня есть расширение для преобразования Enum в SelectList следующим образом:Карта Enum пункты анонимного типа

public static SelectList ToSelectList(this Enum value, Object selected = null) { 

    return new SelectList(Enum.GetValues(value.GetType()).Cast<Enum>().Select(x => 
    new { 
     Value = Convert.ToInt32(x), 
     Description = x.Attribute<DescriptionAttribute>().Description } 
    ), "Value", "Description", selected); 

} 

Это применяется следующим образом:

Countries = new CountryEnum().ToSelectList(currentCountry); 

Это прекрасно работает, но в некоторых случаях мне нужно удалить элемент из списка перечислений или использовать другой порядок, и я не могу это сделать в данный момент.

Поэтому я хотел бы иметь что-то более гибкое. Например:

new CountryEnum() 
    .Map(x => new { 
    Value = Convert.ToInt32(x), 
    Name = x.Attribute<DescriptionAttribute>().Description 
) 
    .OrderBy(x => x.Description) 
    .Remove(x => x.Id > 30) 
    .ToSelectList(... 

Поэтому в основном я хотел бы иметь метод расширения Enum, который картирование перечисления в IEnumerable анонимного типа, который будет использоваться другими методами.

Имеет ли это смысл? Как я могу это сделать?

UPDATE 1

Я попытался следующие:

public static IEnumerable<T> Map<T>(this Enum value, Func<Enum, T> expression) { 

    Type type = value.GetType(); 

    IEnumerable<Enum> items = new List<Enum> { value }; 

    foreach (Enum item in items) 
    yield return expression(item); 

} // Map 

, а затем использовать следующее:

var items = new CountryEnum().Map(x => new { Id = Convert.ToInt32(x) }); 

Но это возвращает 0 ...

UPDATE 2

Я думаю, что решить карту часть следующим образом:

public static IEnumerable<T> Map<T>(this Enum value, Func<Enum, T> expression) { 

    Type type = value.GetType(); 

    var items = Enum.GetValues(type).Cast<Enum>(); 

    foreach (Enum item in items) 
    yield return expression(item); 

} 

Теперь я могу использовать его следующим образом:

new CountryType() 
.Map(x => new { 
    Id = Convert.ToInt32(x), 
    Description = x.Attribute<DescriptionAttribute>().Description }) 
.OrderBy(x => x.Description); 

Теперь то, что я пропускаю это метод расширения, чтобы преобразовать это в a SelectList.

В настоящее время расширение у меня есть:

public static SelectList ToSelectList(this Enum value, Object selected = null) { 

    return new SelectList(Enum.GetValues(value.GetType()).Cast<Enum>().Select(x => new { Value = Convert.ToInt32(x), Description = x.Attribute<DescriptionAttribute>().Description }), "Value", "Description", selected); 

} // ToSelectList 

Так что я хотел бы создать расширение, которое будет применяться после карты одного.

+1

Почему не просто метод расширения, который отображает любое перечисление на IEnumerable >? Почему анонимный тип в счетчике? – olitee

+0

Это имело бы смысл, если бы я всегда хотел только имя и имя Enum. Но иногда мне нужно Enum Id, Name, Description и, возможно, еще один атрибут. –

+0

Я думаю, что все, что вам нужно сделать, это добавить параметры для имен значений и текстовых полей, которые будут переданы конструктору 'SelectedList'. – juharr

ответ

0

Есть ли причина, по которой вы не хотите отображать непосредственно в SelectList?

Что-то больше, как это:

public static SelectList MapToSelectList(this Enum value, 
             Func<Enum, SelectListItem> expression) 
{ 
    Type type = value.GetType(); 

    var items = Enum.GetValues(type).Cast<Enum>(); 

    return new SelectList(
     items.Select(i => expression(i)).ToList()); 
} 

, который позволит вам пройти в FUNC, что дает вам контроль над тем, как перечисление отображается на SelectListItem, как это:

SelectList mySelectList = new CountryType() 
    .MapToSelectList(x => new SelectListItem { 
     Value = Convert.ToInt32(x), 
     Text = x.Attribute<DescriptionAttribute>().Description }); 
0

Я не Не думаю, что вам нужен промежуточный шаг, но вместо этого вы можете пройти Func, которые делают то, что вам нужно, для вашего существующего метода ToSelectList. Вы можете фильтровать перечисления с помощью Func<Enum, bool> и заказать с помощью Func<Enum, T>.Нечто подобное должно добиться того, что вы после:

public static SelectList ToSelectList<T>(this Enum value, 
             Func<Enum, bool> filter, 
             Func<Enum, T> order, 
             bool orderAsc = true, 
             Object selected = null) 
{ 
    //get all values from the enum 
    IEnumerable<Enum> temp = Enum.GetValues(value.GetType()).Cast<Enum>(); 

    //filter if required 
    if (filter != null) 
    { 
     temp = temp.Where(filter); 
    } 

    //order if required 
    if (order != null) 
    { 
     temp = orderAsc ? temp.OrderBy(order) : temp.OrderByDescending(order); 
    } 

    //map to a SelectList 
    return new SelectList(temp.Select(x => 
     new 
     { 
      Value = Convert.ToInt32(x), 
      Description = x.Attribute<DescriptionAttribute>().Description 
     }), "Value", "Description", selected); 
} 

выше может затем быть названо, как это, например, включать только все страны, где стоимость этой страны больше, чем 30 с результатами отсортированы по описание в порядке возрастания и с currentCountry быть выбрано значение:

var Countries = new CountryEnum().ToSelectList(x => Convert.ToInt32(x) > 30, 
               x => x.Attribute<DescriptionAttribute>().Description, 
               true, 
               currentCountry); 

Если обычно требуется выход упорядоченный по описанию в порядке возрастания можно создать небольшой метод обертку для удобства, как это:

public static SelectList ToSelectList(this Enum value, Func<Enum, bool> filter, Object selected = null) 
{ 
    return value.ToSelectList(filter, x => x.Attribute<DescriptionAttribute>().Description, true, selected); 
} 

Что бы упростить выше звонок на что-то вроде этого:

var Countries2 = new CountryEnum().ToSelectList(x => Convert.ToInt32(x) > 30, 
               currentCountry); 
Смежные вопросы