web-dev-qa-db-ja.com

コードからデータ注釈を取得する方法は? (プログラムで)

System.ComponentModel.DataAnnotationsを使用して、Entity Framework 4.1プロジェクトの検証を提供しています。

例えば:

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; }
}

Display.Nameアノテーション値を取得して、などのメッセージに表示する必要があります。選択された「プレイヤー名」はFrankです。

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

注釈を取得する必要がある別の例:

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

どうやってやるの?

48
asmo

拡張方法:

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();
}

コード:

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

これを試して:

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

MaxLengthまたはその他の属性を取得するために使用できる静的メソッドを次に示します。

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);
}

}

静的メソッドの使用...

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

または、インスタンスでオプションの拡張メソッドを使用して...

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

または、他の属性(たとえば、StringLength)に完全な静的メソッドを使用します...

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

ここの答えに触発された... https://stackoverflow.com/a/32501356/324479

4
Carter Medlin

これを実現するには、Reflectionを使用します。実用的なソリューションは here にあります。

0
thmshd

これは私が似たようなことをした方法です

/// <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;
}
0
cnom

here のMetadataTypeAttributeでメタデータクラスを使用するための修正

     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
yamsalm