public class Book
{
[Author("AuthorName")]
public string Name
{
get; private set;
}
}
在我的主要方法中,我正在使用反射,并希望获取每个属性的键值对每个属性。因此,在此示例中,我希望属性名称显示为“ Author”,属性值显示为“ AuthorName”。 ?
#1 楼
使用typeof(Book).GetProperties()
获取PropertyInfo
实例的数组。然后在每个GetCustomAttributes()
上使用PropertyInfo
,以查看它们是否具有Author
属性类型。如果是这样,则可以从属性信息中获取属性的名称,并从属性中获取属性值。返回字典中的数据(请注意,可以通过将类型传递给例程来使数据更加动态):public static Dictionary<string, string> GetAuthors()
{
Dictionary<string, string> _dict = new Dictionary<string, string>();
PropertyInfo[] props = typeof(Book).GetProperties();
foreach (PropertyInfo prop in props)
{
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
AuthorAttribute authAttr = attr as AuthorAttribute;
if (authAttr != null)
{
string propName = prop.Name;
string auth = authAttr.Name;
_dict.Add(propName, auth);
}
}
}
return _dict;
}
评论
我希望我不必强制转换该属性。
–user619891
2011年7月9日在22:14
prop.GetCustomAttributes(true)仅返回一个对象[]。如果您不想进行转换,则可以对属性实例本身使用反射。
–亚当·马克维兹(Adam Markowitz)
2011年7月9日在22:37
什么是AuthorAttribute?它是从Attribute派生的类吗? @亚当·马克维兹
–萨拉斯KS
2014年12月6日7:32
是。 OP正在使用名为“作者”的自定义属性。请参见此处的示例:msdn.microsoft.com/en-us/library/sw480ze8.aspx
–亚当·马克维兹(Adam Markowitz)
2014年12月6日在21:03
与其他所有涉及的操作(空检查和字符串分配除外)相比,强制转换属性的性能开销是微不足道的。
– SilentSin
17年11月21日在5:26
#2 楼
要获得字典中某个属性的所有属性,请使用以下命令:typeof(Book)
.GetProperty("Name")
.GetCustomAttributes(false)
.ToDictionary(a => a.GetType().Name, a => a);
如果还要包括继承的属性,请记住也要从
false
更改为true
。 >评论
这实际上与Adam的解决方案具有相同的作用,但更为简洁。
–丹尼尔·摩尔(Daniel Moore)
2011年7月9日在22:58
如果只需要Author属性并且想跳过将来的转换,则将.OfType
– Adrian Zanescu
2013年9月27日在9:03
当同一属性上有两个相同类型的属性时,会不会抛出异常?
–康斯坦丁
17年2月2日在16:46
#3 楼
如果只需要一个特定的属性值,例如“显示属性”,则可以使用以下代码:var pInfo = typeof(Book).GetProperty("Name")
.GetCustomAttribute<DisplayAttribute>();
var name = pInfo.Name;
#4 楼
我已通过编写通用扩展属性属性帮助程序解决了类似的问题: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);
}
}
用法:
var author = AttributeHelper.GetPropertyAttributeValue<Book, string, AuthorAttribute, string>(prop => prop.Name, attr => attr.Author);
// author = "AuthorName"
评论
如何从const字段获取描述属性?
–阿米尔
2015年11月2日,19:44
您将得到:错误1775成员'Namespace.FieldName'无法通过实例引用进行访问;而是使用类型名称对其进行限定。如果您需要这样做,我建议将“ const”更改为“ readonly”。
– Mikael Engver
2015年11月3日,9:47
老实说,您应该拥有比这更有用的选票。对于许多情况,这是一个非常不错且有用的答案。
–DavidLétourneau
16年1月14日在16:26
谢谢@DavidLétourneau!一个人只能希望。似乎您对此有所帮助。
– Mikael Engver
16年1月14日在19:39
:)您是否认为可以通过使用通用方法为一个类获取所有属性的值,并将该属性的值分配给每个属性?
–DavidLétourneau
16年1月15日在18:51
#5 楼
您可以使用GetCustomAttributesData()
和GetCustomAttributes()
:var attributeData = typeof(Book).GetProperty("Name").GetCustomAttributesData();
var attributes = typeof(Book).GetProperty("Name").GetCustomAttributes(false);
评论
有什么不同?
–Prime By Design
16年4月12日在16:07
@PrimeByDesign前者可以找到如何实例化所应用的属性。后者实际上实例化了那些属性。
– HappyNomad
16年8月31日在22:45
#6 楼
如果您的意思是“对于带有一个参数的属性,列出属性名称和参数值”,则在.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; }
}
#7 楼
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);
}
使用泛型的示例(目标框架4.5)
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);
#8 楼
public static class PropertyInfoExtensions
{
public static TValue GetAttributValue<TAttribute, TValue>(this PropertyInfo prop, Func<TAttribute, TValue> value) where TAttribute : Attribute
{
var att = prop.GetCustomAttributes(
typeof(TAttribute), true
).FirstOrDefault() as TAttribute;
if (att != null)
{
return value(att);
}
return default(TValue);
}
}
用法:
//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);
}
或:
//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();
#9 楼
虽然以上最受好评的答案肯定有效,但在某些情况下,我建议使用略有不同的方法。字典,操作方法如下:var dict = typeof(Book).GetProperties().ToDictionary(p => p.Name, p => p.GetCustomAttributes(typeof(AuthorName), false).Select(a => (AuthorName)a).FirstOrDefault());
它仍然使用强制类型转换,但是可以确保强制类型转换始终有效,因为您只会获得类型为“ AuthorName”的自定义属性。
如果您具有以上多个属性,答案将强制转换。
#10 楼
以下是一些可以用来获取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);
灵感来自Mikael Engver的答案。
#11 楼
死灵法师。对于仍然需要维护.NET 2.0或不使用LINQ的人:
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 );
#12 楼
只是寻找合适的位置放置这段代码。假设您具有以下属性:
[Display(Name = "Solar Radiation (Average)", ShortName = "SolarRadiationAvg")]
public int SolarRadiationAvgSensorId { get; set; }
并且您想要获取ShortName值。您可以执行以下操作:
((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;
}
#13 楼
foreach (var p in model.GetType().GetProperties())
{
var valueOfDisplay =
p.GetCustomAttributesData()
.Any(a => a.AttributeType.Name == "DisplayNameAttribute") ?
p.GetCustomAttribute<DisplayNameAttribute>().DisplayName :
p.Name;
}
在此示例中,我使用DisplayName代替Author,因为它有一个名为'DisplayName'的字段要显示一个值。
#14 楼
要从枚举获取属性,我在使用: 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);
#15 楼
因为在整个应用程序中都使用了许多属性,所以我将其写为动态方法。方法: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));
希望对任何人都有帮助
评论
尝试通过反射访问该对象上的属性时发生了什么情况,是卡在某个地方还是要进行反射的代码