2015-08-05 3 views
4

Я знаю, что дженерики выполняются в сжатые сроки, но я смущен тем, как работают дженерики (и я, хотя я знал дженерики ..).Невозможно использовать метод расширения Enum с общим

Я создал следующий метод расширения:

public static class EnumExt 
{ 
    /// <summary> 
    /// Gets the description, if any, or the name of the enum as a string in a enum type 
    /// </summary> 
    public static string GetDescription<T>(this T enumType) where T : struct, IConvertible 
    { 
     FieldInfo fieldInfo = enumType.GetType().GetField(enumType.ToString()); 
     DescriptionAttribute[] descriptionAttributes = (DescriptionAttribute[]) 
      fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 
     if (descriptionAttributes.Length > 0) 
     { 
      return descriptionAttributes[0].Description; 
     } 
     return enumType.ToString(); 
    } 
} 

меня в качестве примера следующего перечисления

namespace MyProject.Model 
{ 
    [Flags] 
    public enum MyEnumType 
    { 
     [Description("None")] 
     None = 0, 
     [Description("Show Products (default)")] 
     Products = 1, 
     [Description("Show Tariffs")] 
     Tariffs = 2 
    } 
} 

А теперь я хотел бы использовать его из HttpHelper в MVC, который возвращает строка (html text), подобная этой. Обратите внимание: у моего класса есть доступ к моим методам EnumExt.

public static IHtmlString CheckBoxesForEnumModel<TModel>(this HtmlHelper<TModel> htmlHelper) 
    { 
     if (!typeof(TModel).IsEnum) 
     { 
      throw new ArgumentException("this helper can only be used with enums"); 
     } 
     TModel[] allEnumValues = (TModel[])Enum.GetValues(typeof(TModel)); 
     foreach (TModel item in allEnumValues) 
     { 
      var descErr = item.GetDescription(); //does not compile, but I know it's a MyEnumType.Tariffs.. 
      var descOk = MyEnumType.Tariffs.GetDescription(); //this line works 
      //descOk = "Show Tariffs" 
     } 

     return new HtmlString("ideally this is some html checkboxes with each enum description"); 
    } 

Я знаю, что я могу получить все значения Enum и перебирать их, используя TModel так:

TModel[] allEnumValues = (TModel[])Enum.GetValues(typeof(TModel)); 

, но если я знаю, что TModel является перечисление (это MyEnumType), почему я не могу использовать его, чтобы получить доступ к методам расширения перечисления как:

allValues[0].GetDescription<>(); //ERROR. this does not compile 

Я думаю, это потому, что как-то я должен привести его к определенному типу как MyEnumType, но как т o сделать это и сохранить его общим?

Заранее благодарен!

UPDATE: Благодаря первые ответы, которые я смог собрать путем ограничения TModelstruct, IConvertible в

+1

Похоже 'TModel' должен быть' структура, IConvertble' слишком – 2kay

+0

Возможно ли, что путем ограничения '' 'TModel''' к '' 'struct, IConvertible''' и быть неспособным сделать Enum я не могу использовать метод расширения enum GetDescription, потому что он больше не является« реальным »перечислением? Я могу скомпилировать, но '' 'item.GetDescription()' '' не возвращает «Показывать тарифы», но «Тарифы» – iberodev

ответ

3

Потому что ваш метод расширения определен для T where T : struct, IConvertible.

Но TModel в CheckBoxesForEnumModel не соответствует этим ограничениям общего типа.

Вы должны изменить подпись

public static IHtmlString CheckBoxesForEnumModel<TModel>(this HtmlHelper<TModel> htmlHelper) 

в

public static IHtmlString CheckBoxesForEnumModel<TModel>(this HtmlHelper<TModel> htmlHelper) 
    where TModel : struct, IConvertible 

или более ограничительным.

+0

Я ответил nawfal с этим ответом, который также относится к вашему решению: Спасибо. С вашими изменениями он компилируется, однако T в методе расширения, похоже, имеет описаниеAttributes == 0, поэтому он не работает должным образом, поэтому он возвращает строку «Тарифы» вместо «Показывать тарифы» в соответствии с ее атрибутом описания. Я все еще что-то пропустил :( – iberodev

+2

@realavaloro Уверен? Кажется, он отлично работает: http://ideone.com/pvYHQt –

+0

Duh .. У меня была версия без описания. Спасибо и прости. хорошо, как вы говорите. – iberodev

2

Вам необходимо ограничение для вашего метода. Do,

public static IHtmlString CheckBoxesForEnumModel<TModel>(this HtmlHelper<TModel> htmlHelper) where TModel : struct, IConvertible 
{ 
    if (!typeof(TModel).IsEnum) 
    { 
     throw new ArgumentException("this helper can only be used with enums"); 
    } 

    //Here some code to get all the values and the names for this Enum   
    //But HOW?? 

    return new HtmlString("ideally this is some html checkboxes with each enum description"); 
} 

Надеюсь, причина очевидна.

+0

Я из мобильного. Кто-нибудь помогает мне в форматировании. – nawfal

1

Вы создали метод расширения для вашего перечисления, основанный на T где T является struct орудия IConvertible.

Но в методе расширения HtmlHelper ваш TModel не имеют те же ограничения, так что это не так, что компилятор может связать свой метод расширения перечисления на основе типа, который является struct и IConvertible с TModel который только тип ,

Добавление тех же ограничений на ваш метод HtmlHelper будет делать трюк:

public static IHtmlString CheckBoxesForEnumModel<TModel>(this HtmlHelper<TModel> htmlHelper) where TModel : struct, IConvertible 
{ 
    string description = htmlHelper.ViewData.Model.GetDescription(); 
} 
Смежные вопросы