Как получить доступ к атрибуту Description в свойстве или const в C #? - PullRequest
15 голосов
/ 30 марта 2009

Как получить доступ к свойству Description в const или свойстве, т. Е.

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

Я открыт для идей и для других методологий.

EDIT: Я должен был упомянуть, что видел пример, приведенный здесь: Поддерживают ли автоматически реализованные свойства атрибуты?

Однако я ищу способ доступа к атрибуту description без необходимости ввода строкового литерала в тип свойства, то есть я бы предпочел не делать этого:

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

Нечто в духе метода расширения; аналогично следующему методу, который возвращает атрибут Description в Enum через метод расширения:

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

Ответы [ 4 ]

20 голосов
/ 30 марта 2009

Попробуйте следующее

var property = typeof(Group).GetProperty("UserExistsInGroup");
var attribute = property.GetCustomAttributes(typeof(DescriptionAttribute), true)[0];
var description = (DescriptionAttribute)attribute;
var text = description.Description;
4 голосов
/ 30 марта 2009

Вы можете вызвать MemberInfo.GetCustomAttributes () , чтобы получить любые пользовательские атрибуты, определенные для члена Type. Вы можете получить MemberInfo для объекта, выполнив что-то вроде этого:

PropertyInfo prop = typeof(Group).GetProperty("UserExistsInGroup",
    BindingFlags.Public | BindingFlags.Static);
2 голосов
/ 02 февраля 2010

Вот вспомогательный класс, который я использую для обработки пользовательских атрибутов в .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/

2 голосов
/ 30 марта 2009

Хорошо, я видел ваше редактирование, я не уверен, что вы можете сделать это с помощью методов расширения, так как они не знают тип содержащего класса.

Это будет звучать немного странно, но как насчет создания нового класса "DescribedInt", в котором был бы неявный оператор приведения, позволяющий использовать его как int автоматически? Вы сможете использовать в значительной степени, как вы описываете. У вас все еще будет описание, но когда вам понадобится использовать его как Int, вам не нужно получать свойство .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, "");
    //}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...