2016-07-26 4 views
0

У меня есть следующий код:Как получить данные из DisplayAttribute интерфейса?

public interface TestInterface 
{ 
    [Display(Name = "Test Property")] 
    int Property { get; } 
} 

class TestClass : TestAttribute 
{ 
    public int Property { get; set; } 
} 

Заметим, что свойство интерфейса отмечен DisplayAttribute. Когда я пытаюсь получить значение из атрибута, следующие примеры кода не работают.

Первый образец: прямой доступ к собственности класса.

var t = new TestClass(); 

var a = t.GetType().GetProperty("Property").GetCustomAttributes(true); 

Второй образец: литой объект для интерфейса и получить доступ к собственности.

var t = (TestInterface)new TestClass(); 

var a = t.GetType().GetProperty("Property").GetCustomAttributes(true); 

Но когда я передаю объект в качестве модели для MVC зрения и вызова @Html.DisplayNameFor(x => x.Property) возвращает правильную строку "Test Property".

Посмотреть

@model WebApplication1.Models.TestInterface 
... 
@Html.DisplayNameFor(x => x.Property) 

оказывает, как

Test Property 

Как я могу достичь того же результата с кодом на стороне сервера? И почему я не могу сделать это с простым отражением?

+0

Пожалуйста, смотрите на этот вопрос: [Может C# класс наследует атрибуты от интерфейса?] (Http://stackoverflow.com/ вопросы/540749/может-ас-диез-класс-наследует-атрибуты-из-ее-интерфейса). В основном, когда вы реализуете интерфейс, вам нужно обновить атрибуты. –

+0

Обратите внимание, что '@ Html.DisplayNameForm' работает, потому что вы работаете с' TestInterface'. вместо 'TestClass'. –

+0

@Matias во втором примере кода Я тоже работаю с TestInterface –

ответ

1

Вы можете запросить явно связанные типы интерфейсов для аннотаций:

var interfaceAttributes = t.GetType() 
    .GetInterfaces() 
    .Select(x => x.GetProperty("Property")) 
    .Where(x => x != null) // avoid exception with multiple interfaces 
    .SelectMany(x => x.GetCustomAttributes(true)) 
    .ToList(); 

В результате список interfaceAttributes будет содержать DisplayAttribute.

+0

Есть ли способ сделать это проще? –

+0

@MikhailNeofitov На самом деле, я просто должен был сделать это более сложным, чтобы поддерживать интерфейсы без имени запрашиваемого свойства. Предыдущий код бросил исключение – grek40

+0

Ну, его можно отметить как возможное решение. Спасибо –

0

Я сделал что-то подобное для атрибута Description. Вы можете реорганизовать этот код (или лучше, сделать более общий характер), так что он работает для атрибута Display, а не только для перечислений:

public enum LogCategories 
{ 
    [Description("Audit Description")] 
    Audit, 
} 


public static class DescriptionExtensions 
{ 
    public static string GetDescription<T, TType>(this T enumerationValue, TType attribute) 
     where T : struct 
     where TType : DescriptionAttribute 
    { 
     Type type = enumerationValue.GetType(); 
     if (!type.IsEnum) 
     { 
      throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue"); 
     } 

     //Tries to find a DescriptionAttribute for a potential friendly name 
     //for the enum 
     MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString()); 
     if (memberInfo != null && memberInfo.Length > 0) 
     { 
      object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); 

      if (attribute is DescriptionAttribute) 
      { 
       if (attrs != null && attrs.Length > 0) 
       { 
        return ((DescriptionAttribute)attrs[0]).Description; 
       } 
      } 
      else 
      {     
      }     
     } 
     //If we have no description attribute, just return the ToString of the enum 
     return enumerationValue.ToString(); 
    } 
} 

Как вы видите, код использует некоторые отражения для обнаружения каких-либо признаки отмечены на член (в моем случае атрибут DescriptionAttribute, но также может быть атрибутом DisplayAttribute) и возвращает свойство Description вызывающему.

Использование:

string auditDescription = LogCategories.Audit.GetDescription(); // Output: "Audit Description" 
+0

Извлечение элемента переданного объекта аналогично моему первому и второму образцу кода. Он не будет работать с интерфейсом. –

+0

Здесь нет интерфейса, поэтому я не понимаю, что вы здесь пытаетесь сказать. Не могли бы вы уточнить? – hbulens

1

Вы можете попробовать это один

var t = new TestClass(); 
var a = t.GetType().GetInterface("TestInterface").GetProperty("Property").GetCustomAttributes(true); 
+0

Этот код будет работать, но мне нужно больше общего решения, когда я не могу предсказать имя интерфейса. Ответ @ grek40 - это то, что мне нужно –

+0

Я, хотя вы хотите простейшее решение, если вы хотите получить общий вариант, вы должны начать играть с Linq :) или использовать ответ @ grek40, кажется, что это общее – Ebraheem

+0

Простейшим решением будет var a = "Test Property"; :) И я знаю, что через linq и извлечения MemberInfo из MemberExpression я получу требуемое значение. Я надеялся, что могу сделать то же самое с текстовым значением имени свойства. –

Смежные вопросы