C# 反射-获取属性上的属性名称和值

C# 反射-获取属性上的属性名称和值,c#,reflection,propertyinfo,C#,Reflection,Propertyinfo,我有一个类,让我们用一个名为Name的属性称它为Book。对于该属性,我有一个与之关联的属性 public class Book { [Author("AuthorName")] public string Name { get; private set; } } 在我的主要方法中,我使用反射并希望获得每个属性的每个属性的键值对。因此,在本例中,我希望看到属性名为“Author”,属性值为“AuthorName” 问题:如何使用反射获取属性名称

我有一个类,让我们用一个名为Name的属性称它为Book。对于该属性,我有一个与之关联的属性

public class Book
{
    [Author("AuthorName")]
    public string Name
    {
        get; private set; 
    }
}
在我的主要方法中,我使用反射并希望获得每个属性的每个属性的键值对。因此,在本例中,我希望看到属性名为“Author”,属性值为“AuthorName”

问题:如何使用反射获取属性名称和属性值?

使用
typeof(Book).GetProperties()
获取
PropertyInfo
实例数组。然后对每个
PropertyInfo
使用
GetCustomAttributes()
,查看其中是否有
Author
属性类型。如果有,则可以从属性信息中获取属性名称,并从属性中获取属性值

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

}
沿着这些路线扫描类型以查找具有特定属性类型的属性,并在字典中返回数据(请注意,通过将类型传递到例程中,可以使其更具动态性):

publicstaticdictionary GetAuthors()
{
字典_dict=新字典();
PropertyInfo[]props=typeof(Book).GetProperties();
foreach(PropertyInfo props in props)
{
object[]attrs=prop.GetCustomAttributes(true);
foreach(attrs中的对象attr)
{
AuthorAttribute authAttr=attr作为AuthorAttribute;
如果(authAttr!=null)
{
字符串propName=prop.Name;
字符串auth=authAttr.Name;
_dict.Add(propName,auth);
}
}
}
返回命令;
}
您可以使用和:


要获取字典中属性的所有属性,请使用以下命令:

typeof(Book)
  .GetProperty("Name")
  .GetCustomAttributes(false) 
  .ToDictionary(a => a.GetType().Name, a => a);
如果还希望包含继承的属性,请记住从
false
更改为
true

如果您的意思是“对于包含一个参数的属性,请列出属性名称和参数值”,那么在.NET 4.5中,通过
CustomAttributeData
API,这将更容易实现:

using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

public static class Program
{
    static void Main()
    {
        PropertyInfo prop = typeof(Foo).GetProperty("Bar");
        var vals = GetPropertyAttributes(prop);
        // has: DisplayName = "abc", Browsable = false
    }
    public static Dictionary<string, object> GetPropertyAttributes(PropertyInfo property)
    {
        Dictionary<string, object> attribs = new Dictionary<string, object>();
        // look for attributes that takes one constructor argument
        foreach (CustomAttributeData attribData in property.GetCustomAttributesData()) 
        {

            if(attribData.ConstructorArguments.Count == 1)
            {
                string typeName = attribData.Constructor.DeclaringType.Name;
                if (typeName.EndsWith("Attribute")) typeName = typeName.Substring(0, typeName.Length - 9);
                attribs[typeName] = attribData.ConstructorArguments[0].Value;
            }

        }
        return attribs;
    }
}

class Foo
{
    [DisplayName("abc")]
    [Browsable(false)]
    public string Bar { get; set; }
}
使用System.Collections.Generic;
使用系统组件模型;
运用系统反思;
公共静态类程序
{
静态void Main()
{
PropertyInfo prop=typeof(Foo).GetProperty(“Bar”);
var VAL=GetPropertyAttributes(属性);
//has:DisplayName=“abc”,Browsable=false
}
公共静态字典GetPropertyAttributes(PropertyInfo属性)
{
Dictionary attribs=新字典();
//查找采用一个构造函数参数的属性
foreach(属性.GetCustomAttributesData()中的CustomAttributeData属性)
{
if(attribData.ConstructorArguments.Count==1)
{
字符串typeName=attribData.Constructor.DeclaringType.Name;
如果(typeName.EndsWith(“属性”))typeName=typeName.Substring(0,typeName.Length-9);
attribs[typeName]=attribData.ConstructorArguments[0]。值;
}
}
返回属性;
}
}
福班
{
[显示名称(“abc”)]
[可浏览(错误)]
公共字符串条{get;set;}
}

如果您只需要一个特定的属性值作为实例显示属性,则可以使用以下代码:

var pInfo = typeof(Book).GetProperty("Name")
                             .GetCustomAttribute<DisplayAttribute>();
var name = pInfo.Name;
var pInfo=typeof(Book).GetProperty(“名称”)
.GetCustomAttribute();
var name=pInfo.name;

我通过编写一个通用扩展属性帮助器解决了类似的问题:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public static class AttributeHelper
{
    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;
        return attr != null ? valueSelector(attr) : default(TValue);
    }
}
使用系统;
使用System.Linq;
使用System.Linq.Expressions;
运用系统反思;
公共静态类AttributeHelper
{
公共静态TValue GetPropertyAttributeValue(
表达式属性表达式,
Func值选择器)
其中:属性
{
var expression=(MemberExpression)propertyExpression.Body;
var propertyInfo=(propertyInfo)expression.Member;
var attr=propertyInfo.GetCustomAttributes(typeof(tatAttribute),true);
返回属性!=null?值选择器(属性):默认值(TValue);
}
}
用法:

var author = AttributeHelper.GetPropertyAttributeValue<Book, string, AuthorAttribute, string>(prop => prop.Name, attr => attr.Author);
// author = "AuthorName"
 //get class properties with attribute [AuthorAttribute]
        var props = typeof(Book).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(AuthorAttribute)));
            foreach (var prop in props)
            {
               string value = prop.GetAttributValue((AuthorAttribute a) => a.Name);
            }
var objectRelAttr = GetAttribute(typeof(Person), "Country", typeof(ObjectRelationAttribute));

var displayNameAttr = GetAttribute(typeof(Product), "Category", typeof(DisplayNameAttribute));
var author=attributehelp.GetPropertyAttributeValue(prop=>prop.Name,attr=>attr.author);
//author=“AuthorName”
或:

//使用属性[AuthorAttribute]获取类属性
var props=typeof(Book.GetProperties()。其中(prop=>Attribute.IsDefined(prop,typeof(AuthorAttribute));
IList values=props.Select(prop=>prop.getAttributeValue((AuthorAttribute a=>a.Name)).Where(attr=>attr!=null.ToList();
私有静态字典GetAuthors()
{
返回(Book.GetProperties()的类型
.SelectMany(prop=>prop.GetCustomAttributes())
第()类
.ToDictionary(a=>a.GetType().Name.Replace(“属性”),a=>a.Name);
}
使用泛型的示例(目标框架4.5)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
私有静态字典GetAttribute(
Func valueFunc)
其中:属性
{
返回typeof(TType).GetProperties()
.SelectMany(p=>p.GetCustomAttributes())
第()类
.ToDictionary(a=>a.GetType().Name.Replace(“属性”),valueFunc);
}
用法

var dictionary=GetAttribute(a=>a.Name);
foreach(model.GetType().GetProperties()中的var p)
{
显示的var值=
p、 GetCustomAttributesData()
.Any(a=>a.AttributeType.Name==“DisplayNameAttribute”)?
p、 GetCustomAttribute()。显示名称:
p、 姓名;
}

在本例中,我使用DisplayName而不是Author,因为它有一个名为“DisplayName”的字段,该字段将显示一个值。

以下是一些静态方法,可用于获取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)使用完全静态方法。
 //get class properties with attribute [AuthorAttribute]
        var props = typeof(Book).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(AuthorAttribute)));
        IList<string> values = props.Select(prop => prop.GetAttributValue((AuthorAttribute a) => a.Name)).Where(attr => attr != null).ToList();
private static Dictionary<string, string> GetAuthors()
{
    return typeof(Book).GetProperties()
        .SelectMany(prop => prop.GetCustomAttributes())
        .OfType<AuthorAttribute>()
        .ToDictionary(a => a.GetType().Name.Replace("Attribute", ""), a => a.Name);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

private static Dictionary<string, string> GetAttribute<TAttribute, TType>(
    Func<TAttribute, string> valueFunc)
    where TAttribute : Attribute
{
    return typeof(TType).GetProperties()
        .SelectMany(p => p.GetCustomAttributes())
        .OfType<TAttribute>()
        .ToDictionary(a => a.GetType().Name.Replace("Attribute", ""), valueFunc);
}
var dictionary = GetAttribute<AuthorAttribute, Book>(a => a.Name);
foreach (var p in model.GetType().GetProperties())
{
   var valueOfDisplay = 
       p.GetCustomAttributesData()
        .Any(a => a.AttributeType.Name == "DisplayNameAttribute") ? 
            p.GetCustomAttribute<DisplayNameAttribute>().DisplayName : 
            p.Name;
}
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);
var length = AttributeHelpers.GetPropertyAttributeValue<Player,string,StringLengthAttribute,Int32>(prop => prop.PlayerName,attr => attr.MaximumLength);
public static object GetAttribute(System.Reflection.MemberInfo mi, System.Type t)
{
    object[] objs = mi.GetCustomAttributes(t, true);

    if (objs == null || objs.Length < 1)
        return null;

    return objs[0];
}



public static T GetAttribute<T>(System.Reflection.MemberInfo mi)
{
    return (T)GetAttribute(mi, typeof(T));
}


public delegate TResult GetValue_t<in T, out TResult>(T arg1);

public static TValue GetAttributValue<TAttribute, TValue>(System.Reflection.MemberInfo mi, GetValue_t<TAttribute, TValue> value) where TAttribute : System.Attribute
{
    TAttribute[] objAtts = (TAttribute[])mi.GetCustomAttributes(typeof(TAttribute), true);
    TAttribute att = (objAtts == null || objAtts.Length < 1) ? default(TAttribute) : objAtts[0];
    // TAttribute att = (TAttribute)GetAttribute(mi, typeof(TAttribute));

    if (att != null)
    {
        return value(att);
    }
    return default(TValue);
}
System.Reflection.FieldInfo fi = t.GetField("PrintBackground");
wkHtmlOptionNameAttribute att = GetAttribute<wkHtmlOptionNameAttribute>(fi);
string name = GetAttributValue<wkHtmlOptionNameAttribute, string>(fi, delegate(wkHtmlOptionNameAttribute a){ return a.Name;});
string aname = GetAttributValue<wkHtmlOptionNameAttribute, string>(fi, a => a.Name );
 public enum ExceptionCodes
 {
  [ExceptionCode(1000)]
  InternalError,
 }

 public static (int code, string message) Translate(ExceptionCodes code)
        {
            return code.GetType()
            .GetField(Enum.GetName(typeof(ExceptionCodes), code))
            .GetCustomAttributes(false).Where((attr) =>
            {
                return (attr is ExceptionCodeAttribute);
            }).Select(customAttr =>
            {
                var attr = (customAttr as ExceptionCodeAttribute);
                return (attr.Code, attr.FriendlyMessage);
            }).FirstOrDefault();
        }
 var _message = Translate(code);
[Display(Name = "Solar Radiation (Average)", ShortName = "SolarRadiationAvg")]
public int SolarRadiationAvgSensorId { get; set; }
((DisplayAttribute)(typeof(SensorsModel).GetProperty(SolarRadiationAvgSensorId).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName;
internal static string GetPropertyAttributeShortName(string propertyName)
{
    return ((DisplayAttribute)(typeof(SensorsModel).GetProperty(propertyName).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName;
}
var dict = typeof(Book).GetProperties().ToDictionary(p => p.Name, p => p.GetCustomAttributes(typeof(AuthorName), false).Select(a => (AuthorName)a).FirstOrDefault());
public static dynamic GetAttribute(Type objectType, string propertyName, Type attrType)
    {
        //get the property
        var property = objectType.GetProperty(propertyName);

        //check for object relation
        return property.GetCustomAttributes().FirstOrDefault(x => x.GetType() == attrType);
    }
var objectRelAttr = GetAttribute(typeof(Person), "Country", typeof(ObjectRelationAttribute));

var displayNameAttr = GetAttribute(typeof(Product), "Category", typeof(DisplayNameAttribute));