2013-12-03 5 views
0

Я создаю пользовательский атрибут. И я буду использовать его в нескольких классах:Получить пользовательские атрибуты Общий

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] 
public sealed class Display : System.Attribute 
{ 
    public string Name { get; set; } 

    public string Internal { get; set; } 

} 

public class Class1 
{ 
    [Display(Name = "ID")] 
    public int ID { get; set; } 

    [Display(Name = "Name")] 
    public string Title { get; set; } 
} 

public class Class2 
{ 
    [Display(Name = "ID")] 
    public int ID { get; set; } 

    [Display(Name = "Name")] 
    public string Title { get; set; } 
} 

Здесь работает правильно, но я хочу, чтобы сделать его максимально стандартизован, как пример MVC:

Class1 class1 = new Class1(); 
class1.Title.DisplayName()// returns the value "Name" 

Единственное, что я мог сделать сформировать петлю моей собственности, но мне нужно, чтобы сообщить мой TypeOf Class1

foreach (var prop in typeof(Class1).GetProperties()) 
{ 
    var attrs = (Display[])prop.GetCustomAttributes(typeof(Display), false); 
    foreach (var attr in attrs) 
    { 
     Console.WriteLine("{0}: {1}", prop.Name, attr.Name); 
    } 
} 

есть ли способ сделать это так, как я хочу?

+0

Вы никогда не говорили, что хотите .. Не могли бы вы уточнить? –

+0

Я хотел бы расширить метод, чтобы вернуть значение атрибута отображения. Что-то вроде этого: class1.Title.DisplayName(); // возвращает значение «Имя» – Tiago

+0

Я не думаю, что это возможно - когда вы получаете значение свойства, оно теряет соединение с классом, где оно расположено, поэтому вы не можете создать метод расширения, который находит собственный класс по значению свойство (это действительно то же самое, что и попытка получить атрибут константы 'string' из' int') ... –

ответ

4

Вы не можете выполнить то, что вы показали точно, потому что class1.Title - это выражение, которое оценивает строку. Вы ищете метаданные об объекте Title. Вы можете использовать деревья выражений, чтобы вы могли написать что-то близкое. Вот короткий вспомогательный класс, который тянет значение атрибута из свойства в дереве выражения:

public static class PropertyHelper 
{ 
    public static string GetDisplayName<T>(Expression<Func<T, object>> propertyExpression) 
    { 
     Expression expression; 
     if (propertyExpression.Body.NodeType == ExpressionType.Convert) 
     { 
      expression = ((UnaryExpression)propertyExpression.Body).Operand; 
     } 
     else 
     { 
      expression = propertyExpression.Body; 
     } 

     if (expression.NodeType != ExpressionType.MemberAccess) 
     { 
      throw new ArgumentException("Must be a property expression.", "propertyExpression"); 
     } 

     var me = (MemberExpression)expression; 
     var member = me.Member; 
     var att = member.GetCustomAttributes(typeof(DisplayAttribute), false).OfType<DisplayAttribute>().FirstOrDefault(); 
     if (att != null) 
     { 
      return att.Name; 
     } 
     else 
     { 
      // No attribute found, just use the actual name. 
      return member.Name; 
     } 
    } 

    public static string GetDisplayName<T>(this T target, Expression<Func<T, object>> propertyExpression) 
    { 
     return GetDisplayName<T>(propertyExpression); 
    } 
} 

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

public static void Main(string[] args) 
{ 
    Class1 class1 = new Class1(); 
    Console.WriteLine(class1.GetDisplayName(c => c.Title)); 
    Console.WriteLine(PropertyHelper.GetDisplayName<Class1>(c => c.Title)); 
} 
+0

Удивительно работает отлично, вы парень – Tiago

+0

Просто обратите внимание, что этот метод работает так, когда мой метод имеет тип строка. Если это иначе, то это не относится к ошибке: "if (propertyExpression.Body.NodeType! = ExpressionType.MemberAccess)" пример: "class1.GetDisplayName (c => c.ID)" – Tiago

+0

@Tiago В случае свойства типа значения вставляется неявное преобразование в объект. Обновлен пример обработки этого случая. –

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