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

发布于 2024-11-28 23:57:16 字数 756 浏览 6 评论 0原文

我正在使用 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 注释值以在消息中显示它,例如 The selected "Player Name" is Frank.

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

为什么我需要检索注释的另一个例子:

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

我怎样才能做到这一点?

I'm using System.ComponentModel.DataAnnotations to provide validation for my Entity Framework 4.1 project.

For example:

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

I need to retrieve the Display.Name annotation value to show it in a message such as The chosen "Player Name" is Frank.

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

Another example of why I could need to retrieve annotations:

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

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

南笙 2024-12-05 23:57:16

扩展方法:

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>(nameof(player.PlayerDescription)).Name;
var maxLength = player.GetAttributeFrom<MaxLengthAttribute>(nameof(player.PlayerName)).Length;

Extension method:

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

Code:

var name = player.GetAttributeFrom<DisplayAttribute>(nameof(player.PlayerDescription)).Name;
var maxLength = player.GetAttributeFrom<MaxLengthAttribute>(nameof(player.PlayerName)).Length;
一张白纸 2024-12-05 23:57:16

试试这个:

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

try this:

((DisplayAttribute)
  (myPlayer
    .GetType()
    .GetProperty("PlayerName")
    .GetCustomAttributes(typeof(DisplayAttribute),true)[0])).Name;
软糯酥胸 2024-12-05 23:57:16

以下是一些可用于获取 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

Here are some static methods you can use to get the MaxLength, or any other attribute.

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

}

Using the static method...

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

Or using the optional extension method on an instance...

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

Or using the full static method for any other attribute (StringLength for example)...

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

Inspired by the answer here...
https://stackoverflow.com/a/32501356/324479

缱绻入梦 2024-12-05 23:57:16

这就是我做类似事情的方式

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

This is how I have done something similar

/// <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;
}
酷炫老祖宗 2024-12-05 23:57:16

因为 https://stackoverflow.com/a/7027791/7173655 上的接受答案仍然使用魔术常量,所以我分享我的基于链接答案的代码:

扩展方法:

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;

Because the acceptet answer on https://stackoverflow.com/a/7027791/7173655 still uses magic constants, I share my code based on the linked answer:

Extension method:

public static TA GetAttributeFrom<TC,TA>(string propertyName) where TA : Attribute {
    return (TA)typeof(TC).GetProperty(propertyName)
        .GetCustomAttributes(typeof(TA), false).SingleOrDefault();
}

Usage without magic constants (assuring refactoring does hurt less):

var nameMaxLength = device.GetAttributeFrom<StringLengthAttribute>(nameof(device.name)).MaximumLength;
故事与诗 2024-12-05 23:57:16

我认为这个例子 https://github.com/TeteStorm/DataAnnotationScan 非常有用。

我只是为了让 EF 在我的模型装配中使用数据注释,但请随意 fork 并根据需要进行更改。

更改以下方法 HasEFDataAnnotation 并享受乐趣!

https://github.com/TeteStorm/DataAnnotationScan


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

I think so that this example https://github.com/TeteStorm/DataAnnotationScan can be very usefull.

I maide just to get EF used Data Annotations at my model assembly, but feel free for fork and change as you need.

Change the below method HasEFDataAnnotaion and have fun!

https://github.com/TeteStorm/DataAnnotationScan


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

咋地 2024-12-05 23:57:16

修复了使用元数据类与 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; 
    }

a Fix for using metadata Class with MetadataTypeAttribute from 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; 
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文