Подтвердить что ты не робот

Как получить доступ к атрибуту Description в качестве свойства или константы в С#?

Как вы получаете доступ к свойству 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: Я должен был упомянуть, что я видел пример, приведенный здесь: Имеют ли атрибуты, поддерживающие автообновление, атрибуты?

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

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

Ответ 1

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

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

Ответ 2

Попробуйте выполнить

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

Ответ 3

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

Это будет звучать немного странно, но как насчет создания нового класса "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, "");
    //}
}

Ответ 4

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