如何在C#中访问属性或常量的Description属性?

24

如何访问常量或属性上的描述(Description)属性?

public static class Group
{

    [Description( "Specified parent-child relationship already exists." )]
    public const int ParentChildRelationshipExists = 1;

    [Description( "User is already a member of the group." )]
    public const int UserExistsInGroup = 2;

}
或者
public static class Group
{

    [Description( "Specified parent-child relationship already exists." )]
    public static int ParentChildRelationshipExists { 
      get { return 1; } 
    }

    [Description( "User is already a member of the group." )]
    public static int UserExistsInGroup { 
      get { return 2; } 
    }

}

在调用类中,我想要访问Description属性,即:

int x = Group.UserExistsInGroup;
string description = Group.UserExistsInGroup.GetDescription(); // or similar

我也愿意接受其他方法的建议。

编辑: 我应该提到,我在这里看到了一个示例: 自动实现的属性支持属性吗?

但是,我正在寻找一种方法来访问描述属性,而不必将字符串文字输入到属性类型中,即,我不想这样做:

typeof(Group).GetProperty("UserExistsInGroup");

类似于扩展方法的东西;可以通过扩展方法返回枚举值上的描述属性,就像以下方法一样:

public static String GetEnumDescription( this Enum obj )
{
    try
    {
        System.Reflection.FieldInfo fieldInfo = 
            obj.GetType().GetField( obj.ToString() );

        object[] attribArray = fieldInfo.GetCustomAttributes( false );

        if (attribArray.Length > 0)
        {
            var attrib = attribArray[0] as DescriptionAttribute;

            if( attrib != null  )
                return attrib.Description;
        }
        return obj.ToString();
    }
    catch( NullReferenceException ex )
    {
        return "Unknown";
    }
}

回复您的编辑:请参考此链接http://www.codeproject.com/Articles/28514/Strong-Reflection-without-magic-strings,以安全地获取属性信息。 - walpen
4个回答

29

尝试以下方法

var property = typeof(Group).GetProperty("UserExistsInGroup");
var attribute = property.GetCustomAttributes(typeof(DescriptionAttribute), true)[0];
var description = (DescriptionAttribute)attribute;
var text = description.Description;

@JaredPar - 抱歉,我应该澄清一下,请看我的编辑。 - Metro Smurf
我知道这是一个相当老的答案,但不应该是var description = (DescriptionAttribute)attribute;吗? - Jack

6

您可以调用MemberInfo.GetCustomAttributes()方法来获取Type中成员定义的任何自定义属性。您可以通过以下方式获取属性的MemberInfo

PropertyInfo prop = typeof(Group).GetProperty("UserExistsInGroup",
    BindingFlags.Public | BindingFlags.Static);

我认为这是不可能的,至少使用你现在的属性是不行的。你需要获取属性的 PropertyInfo,而唯一的方法就是通过属性名称来查找它。 - Andy

3
这是我在.NET中使用的一个辅助类,用于处理自定义属性。
public class AttributeList : List<Attribute>
{
    /// <summary>
    /// Gets a list of custom attributes
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static AttributeList GetCustomAttributeList(ICustomAttributeProvider propertyInfo)
    {
        var result = new AttributeList();
        result.AddRange(propertyInfo.GetCustomAttributes(false).Cast<Attribute>());
        return result;
    }

    /// <summary>
    /// Finds attribute in collection by its type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T FindAttribute<T>() where T : Attribute
    {
        return (T)Find(x => typeof(T).IsAssignableFrom(x.GetType()));
    }

    public bool IsAttributeSet<T>() where T : Attribute
    {
        return FindAttribute<T>() != null;
    }
}

此外还有针对MsTest的单元测试,展示如何使用该类

[TestClass]
public class AttributeListTest
{
    private class TestAttrAttribute : Attribute
    {
    }

    [TestAttr]
    private class TestClass
    {
    }

    [TestMethod]
    public void Test()
    {
        var attributeList = AttributeList.GetCustomAttributeList(typeof (TestClass));
        Assert.IsTrue(attributeList.IsAttributeSet<TestAttrAttribute>());
        Assert.IsFalse(attributeList.IsAttributeSet<TestClassAttribute>());
        Assert.IsInstanceOfType(attributeList.FindAttribute<TestAttrAttribute>(), typeof(TestAttrAttribute));
    }
}

http://www.kozlenko.info/2010/02/02/getting-a-list-of-custom-attributes-in-net/


我已经让它工作了,这是我的代码:var attributeList = AttributeList.GetCustomAttributeList(MethodInfo.GetCurrentMethod());var attribute = attributeList.FindAttribute<DescriptionAttribute>().Description; - Omzig

2

好的,我看到了你的编辑。我不确定你是否可以使用扩展方法来实现,因为它们可能不知道包含类别的类型。

这听起来有点古怪,但创建一个新类"DescribedInt"如何?该类会有一个隐式转换运算符,使您能够自动将其用作整数。您可以按照自己的描述方式使用它。虽然仍然有一个描述,但当您需要像使用整数一样使用它时,您不需要获取.Data属性......

例如:

private void ExampleUse()
{
    int myvalue = Group.A; //see, no need to cast or say ".Data" - implicit cast
    string text = Group.A.Description;

//使用值进行操作... }

public static class Group
{
    public static DescribedInt A = new DescribedInt(12, "some description");
    public static DescribedInt B = new DescribedInt(88, "another description");
}

public class DescribedInt
{
    public readonly int data;
    public readonly string Description;

    public DescribedInt(int data, string description)
    {
        this.data = data;
        this.Description = description;
    }

    //automatic cast to int
    public static implicit operator int(DescribedInt orig)
    {
        return orig.data;
    }

    //public DescribedInt(string description)
    //{
    //    this.description = description;
    //}

    //if you ever need to go the "other way"
    //public static implicit operator DescribedInt(int orig)
    //{
    //    return new DescribedInt(orig, "");
    //}
}

@Ilya - 这可能是一个可行的替代方案。我明天会仔细看一下。谢谢! - Metro Smurf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接