2011-08-11 11 views
36

Używam System.ComponentModel.DataAnnotations do sprawdzania poprawności mojego projektu Entity Framework 4.1.Jak pobierać adnotacje danych z kodu? (programowo)

Na przykład:

public class Player 
{ 
    [Required] 
    [MaxLength(30)] 
    [Display(Name = "Player Name")] 
    public string PlayerName { get; set; } 

    [MaxLength(100)] 
    [Display(Name = "Player Description")] 
    public string PlayerDescription{ get; set; } 
} 

muszę pobrać wartość Display.Name adnotacji, aby pokazać je w wiadomości, takie jak Wybrany „Nazwa gracza” jest Frank.

=============== ====================================

Kolejny przykład, dlaczego mogę potrzebować pobrać adnotacje :

var playerNameTextBox = new TextBox(); 
playerNameTextBox.MaxLength = GetAnnotation(myPlayer.PlayerName, MaxLength); 

Jak mogę to zrobić?

+0

Proszę spojrzeć na ten post http://stackoverflow.com/questions/803221/c-reflection-finding-attributes-on-a-ember-field to pokazuje jak możesz to zrobić za pomocą refleksji. – Jethro

Odpowiedz

70

metoda Extension:

public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute 
{ 
    var attrType = typeof(T); 
    var property = instance.GetType().GetProperty(propertyName); 
    return (T)property .GetCustomAttributes(attrType, false).First(); 
} 

Kod:

var name = player.GetAttributeFrom<DisplayAttribute>("PlayerDescription").Name; 
var maxLength = player.GetAttributeFrom<MaxLengthAttribute>("PlayerName").Length; 
+2

Popraw mnie, jeśli się mylę, ale myślę, że nie zadziałałoby, gdyby w klasie Gracza występował więcej niż jeden atrybut DisplayAttribute (co prawie zawsze będzie miało miejsce). Zobacz mój zaktualizowany kod w moim pytaniu. – asmo

+0

próbka kodu została zaktualizowana. – jgauffin

+0

Jeśli adnotacja nie istnieje w atrybucie, zostanie zbombardowana.Jeśli jest możliwe, że adnotacja nie istnieje, użyj 'FirstOrDefault()' zamiast 'First()' –

0

Chcesz użyć Reflection, aby to osiągnąć. Roztwór roboczy można znaleźć here.

5

spróbuj tego:

((DisplayAttribute) 
    (myPlayer 
    .GetType() 
    .GetProperty("PlayerName") 
    .GetCustomAttributes(typeof(DisplayAttribute),true)[0])).Name; 
0

poprawka dla klasy przy użyciu metadanych z MetadataTypeAttribute od here

 public T GetAttributeFrom<T>(object instance, string propertyName) where T : Attribute 
    { 
     var attrType = typeof(T); 
     var property = instance.GetType().GetProperty(propertyName); 
     T t = (T)property.GetCustomAttributes(attrType, false).FirstOrDefault(); 
     if (t == null) 
     { 
      MetadataTypeAttribute[] metaAttr = (MetadataTypeAttribute[])instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true); 
      if (metaAttr.Length > 0) 
      { 
       foreach (MetadataTypeAttribute attr in metaAttr) 
       { 
        var subType = attr.MetadataClassType; 
        var pi = subType.GetField(propertyName); 
        if (pi != null) 
        { 
         t = (T)pi.GetCustomAttributes(attrType, false).FirstOrDefault(); 
         return t; 
        } 


       } 
      } 

     } 
     else 
     { 
      return t; 
     } 
     return null; 
    } 
0

To jak mam zrobić coś podobnego

/// <summary> 
/// Returns the DisplayAttribute of a PropertyInfo (field), if it fails returns null 
/// </summary> 
/// <param name="propertyInfo"></param> 
/// <returns></returns> 
private static string TryGetDisplayName(PropertyInfo propertyInfo) 
{ 
    string result = null; 
    try 
    { 
     var attrs = propertyInfo.GetCustomAttributes(typeof(DisplayAttribute), true); 
     if (attrs.Any()) 
      result = ((DisplayAttribute)attrs[0]).Name; 
    } 
    catch (Exception) 
    { 
     //eat the exception 
    } 
    return result; 
} 
1

Oto kilka statyczne metody można użyć, aby uzyskać MaxLength lub jakąkolwiek inną cechę.

using System; 
using System.Linq; 
using System.Reflection; 
using System.ComponentModel.DataAnnotations; 
using System.Linq.Expressions; 

public static class AttributeHelpers { 

public static Int32 GetMaxLength<T>(Expression<Func<T,string>> propertyExpression) { 
    return GetPropertyAttributeValue<T,string,MaxLengthAttribute,Int32>(propertyExpression,attr => attr.Length); 
} 

//Optional Extension method 
public static Int32 GetMaxLength<T>(this T instance,Expression<Func<T,string>> propertyExpression) { 
    return GetMaxLength<T>(propertyExpression); 
} 


//Required generic method to get any property attribute from any class 
public static TValue GetPropertyAttributeValue<T, TOut, TAttribute, TValue>(Expression<Func<T,TOut>> propertyExpression,Func<TAttribute,TValue> valueSelector) where TAttribute : Attribute { 
    var expression = (MemberExpression)propertyExpression.Body; 
    var propertyInfo = (PropertyInfo)expression.Member; 
    var attr = propertyInfo.GetCustomAttributes(typeof(TAttribute),true).FirstOrDefault() as TAttribute; 

    if (attr==null) { 
     throw new MissingMemberException(typeof(T).Name+"."+propertyInfo.Name,typeof(TAttribute).Name); 
    } 

    return valueSelector(attr); 
} 

} 

Stosując metodę statyczną ...

var length = AttributeHelpers.GetMaxLength<Player>(x => x.PlayerName); 

lub za pomocą opcjonalnego metodę rozszerzenia na wystąpienie ...

var player = new Player(); 
var length = player.GetMaxLength(x => x.PlayerName); 

Albo metodą pełną statycznego dla dowolnego innego atrybutu (StringLength na przykład) ...

var length = AttributeHelpers.GetPropertyAttributeValue<Player,string,StringLengthAttribute,Int32>(prop => prop.PlayerName,attr => attr.MaximumLength); 

Zainspirowany odpowiedzią tutaj ... https://stackoverflow.com/a/32501356/324479

Powiązane problemy