C# 如何从代码中检索数据注释?(以编程方式)

C# 如何从代码中检索数据注释?(以编程方式),c#,entity-framework-4.1,data-annotations,C#,Entity Framework 4.1,Data Annotations,我正在使用System.ComponentModel.DataAnnotations为我的EntityFramework4.1项目提供验证 例如: public class Player { [Required] [MaxLength(30)] [Display(Name = "Player Name")] public string PlayerName { get; set; } [MaxLength(100)] [Display(Name

我正在使用
System.ComponentModel.DataAnnotations
为我的EntityFramework4.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
注释值,以便在消息中显示它,例如所选的“Player Name”是Frank

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

我可能需要检索注释的另一个示例:

var playerNameTextBox = new TextBox();
playerNameTextBox.MaxLength = GetAnnotation(myPlayer.PlayerName, MaxLength);
我如何才能做到这一点?

扩展方法:

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();
}
public static TA GetAttributeFrom<TC,TA>(string propertyName) where TA : Attribute {
    return (TA)typeof(TC).GetProperty(propertyName)
        .GetCustomAttributes(typeof(TA), false).SingleOrDefault();
}
public static T GetAttributeFrom(此对象实例,string propertyName),其中T:Attribute
{
var attrType=typeof(T);
var property=instance.GetType().GetProperty(propertyName);
return(T)property.GetCustomAttributes(attrType,false).First();
}
代码:

var name=player.GetAttributeFrom(nameof(player.PlayerDescription)).name;
var maxLength=player.GetAttributeFrom(nameof(player.PlayerName)).Length;
试试这个:

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

修复了使用MetadataTypeAttribute的元数据类的问题

public T GetAttributeFrom(对象实例,字符串propertyName),其中T:Attribute
{
var attrType=typeof(T);
var property=instance.GetType().GetProperty(propertyName);
T=(T)property.GetCustomAttributes(attrType,false).FirstOrDefault();
如果(t==null)
{
MetadataTypeAttribute[]metaAttr=(MetadataTypeAttribute[])实例.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute),true);
如果(metaAttr.Length>0)
{
foreach(metaAttr中的MetadataTypeAttribute attr)
{
var subType=attr.MetadataClassType;
var pi=subType.GetField(propertyName);
如果(pi!=null)
{
t=(t)pi.GetCustomAttributes(attrType,false).FirstOrDefault();
返回t;
}
}
}
}
其他的
{
返回t;
}
返回null;
}

我就是这样做的

/// <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;
}
//
///返回PropertyInfo(字段)的DisplayAttribute,如果失败,则返回null
/// 
/// 
/// 
私有静态字符串TryGetDisplayName(PropertyInfo PropertyInfo)
{
字符串结果=null;
尝试
{
var attrs=propertyInfo.GetCustomAttributes(typeof(DisplayAttribute),true);
if(attrs.Any())
结果=((DisplayAttribute)属性[0])。名称;
}
捕获(例外)
{
//吃破例
}
返回结果;
}

以下是一些静态方法,可用于获取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);
}

}
或者对任何其他属性(例如StringLength)使用完全静态方法

var length=AttributeHelpers.GetPropertyAttributeValue(prop=>prop.PlayerName,attr=>attr.MaximumLength);
受这里答案的启发。。。

由于上的acceptet答案仍然使用魔法常数,因此我根据链接答案共享代码:

扩展方法:

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();
}
public static TA GetAttributeFrom<TC,TA>(string propertyName) where TA : Attribute {
    return (TA)typeof(TC).GetProperty(propertyName)
        .GetCustomAttributes(typeof(TA), false).SingleOrDefault();
}
公共静态TA GetAttributeFrom(string propertyName),其中TA:Attribute{
返回(TA)类型(TC).GetProperty(propertyName)
.GetCustomAttributes(typeof(TA),false).SingleOrDefault();
}
使用时不使用神奇常量(确保重构不会造成太大伤害):

var nameMaxLength=device.GetAttributeFrom(nameof(device.name)).MaximumLength;

我认为这个例子非常有用

我只是想在我的模型组件中获得EF使用的数据注释,但可以根据需要自由使用fork和change

更改下面的方法HasefDataAnnotation并享受乐趣


如果我错了,请纠正我的错误,但我认为如果Player类中存在多个DisplayAttribute,那么它将不起作用(几乎总是这样)。在我的问题中查看我的更新代码。如果属性上不存在注释,这将导致爆炸。如果注释可能不存在,请使用
FirstOrDefault()
而不是
First()
示例代码无论如何都会“爆炸”,因为没有空检查;)将属性名称硬编码为字符串将消除重构代码的能力。总有一天这些代码可能会咬到你。你想用反射来实现这一点。可以找到一个有效的解决方案。请看这篇文章,它向你展示了如何使用反射来实现这一点。
var player = new Player();
var length = player.GetMaxLength(x => x.PlayerName);
var length = AttributeHelpers.GetPropertyAttributeValue<Player,string,StringLengthAttribute,Int32>(prop => prop.PlayerName,attr => attr.MaximumLength);
public static TA GetAttributeFrom<TC,TA>(string propertyName) where TA : Attribute {
    return (TA)typeof(TC).GetProperty(propertyName)
        .GetCustomAttributes(typeof(TA), false).SingleOrDefault();
}
var nameMaxLength = device.GetAttributeFrom<StringLengthAttribute>(nameof(device.name)).MaximumLength;

        private static bool HasEFDataAnnotaion(PropertyInfo[] properties)
        {
            return properties.ToList().Any((property) =>
            {
                var attributes = property.GetCustomAttributes(false);
                Attribute[] attrs = System.Attribute.GetCustomAttributes(property);
                return attrs.Any((attr) =>
                {
                    return attr is KeyAttribute || attr is ForeignKeyAttribute || attr is IndexAttribute || attr is RequiredAttribute || attr is TimestampAttribute
                    || attr is ConcurrencyCheckAttribute || attr is MinLengthAttribute || attr is MinLengthAttribute
                    || attr is MaxLengthAttribute || attr is StringLengthAttribute || attr is TableAttribute || attr is ColumnAttribute
                    || attr is DatabaseGeneratedAttribute || attr is ComplexTypeAttribute;
                });
            });
        }