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

System.ComponentModel.DescriptionAttribute в портативной библиотеке классов

Я использую атрибут Description в своих перечислениях для предоставления удобного имени в поле перечисления. например.

public enum InstallationType
{
    [Description("Forward of Bulk Head")]
    FORWARD = 0,

    [Description("Rear of Bulk Head")]
    REAR = 1,

    [Description("Roof Mounted")]
    ROOF = 2,
}

И доступ к этому легко с помощью хорошего вспомогательного метода:

public static string GetDescriptionFromEnumValue(Enum value)
    {
        DescriptionAttribute attribute = value.GetType()
            .GetField(value.ToString())
            .GetCustomAttributes(typeof(DescriptionAttribute), false)
            .SingleOrDefault() as DescriptionAttribute;
        return attribute == null ? value.ToString() : attribute.Description;
    }

Мне нужно преобразовать это в переносимую библиотеку классов, но у него нет доступа к библиотеке System.ComponentModel. когда я пытаюсь добавить уважение, VS говорит мне, что я уже ссылался на все.

Спасибо

4b9b3361

Ответ 1

Так как DescriptionAttribute недоступен для портативных библиотек классов, вам нужно использовать другой атрибут. Пространство имен System.ComponentModel.DataAnnotations, которое доступно для переносимых библиотек классов, предоставляет атрибут DisplayAttribute, который вы можете использовать вместо этого.

public enum InstallationType
{
    [Display(Description="Forward of Bulk Head")]
    FORWARD = 0,

    [Display(Description="Rear of Bulk Head")]
    REAR = 1,

    [Display(Description="Roof Mounted")]
    ROOF = 2,
}

Ваш метод необходимо изменить на

public static string GetDescriptionFromEnumValue(Enum value)
    {
        DisplayAttribute attribute = value.GetType()
            .GetField(value.ToString())
            .GetCustomAttributes(typeof(DisplayAttribute ), false)
            .SingleOrDefault() as DisplayAttribute ;
        return attribute == null ? value.ToString() : attribute.Description;
    }

Ответ 2

Является ли что-то доступным для переносимой библиотеки классов, зависит от того, какие рамки вы выбрали для библиотеки - вы получаете только строгое пересечение. Однако вполне возможно, что этот атрибут просто не существует в одной из ваших целевых инфраструктур. В этом случае один вариант добавляет ваш собственный - тогда вы знаете, что он доступен. Например:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumDescriptionAttribute :Attribute
{
    private readonly string description;
    public string Description { get { return description; } }
    public EnumDescriptionAttribute(string description)
    {
        this.description = description;
    }
}

enum Foo
{
    [EnumDescription("abc")]
    A,
    [EnumDescription("def")]
    B
}

Обратите внимание, что я намеренно не включил здесь дополнительных конструкторов сериализации, поскольку они также зависят от функций, которые недоступны для всех фреймворков. Изменение кода с помощью [Description]/DescriptionAttribute до [EnumDescription]/EnumDescriptionAttribute должно быть довольно тривиальным.

Ответ 3

Попробуйте это для получения атрибута enum в портативных библиотеках:

public static class EnumsHelper
{
    public static T GetAttributeOfType<T>(this Enum enumVal) where T : Attribute
    {
        var typeInfo = enumVal.GetType().GetTypeInfo();
        var v = typeInfo.DeclaredMembers.First(x => x.Name == enumVal.ToString());
        return v.GetCustomAttribute<T>();
    }
}

Обновить: также вы должны объявить новый атрибут (см. описаниеAttribute, не доступный в PCL), например следующий:

public class MyDescriptionAttribute : Attribute
{
    public virtual string Text { get; set; }
}

и добавьте еще один метод в класс EnumsHelper:

public static class EnumsHelper
{
    ...

    public static string GetDescription(this Enum enumVal)
    {
        var attr = GetAttributeOfType<MyDescriptionAttribute>(enumVal);
        return attr != null ? attr.Text : string.Empty;
    }
}

и если у вас есть следующее перечисление:

public enum InstallationType
{
    [MyDescription(Text = "Forward of Bulk Head")]
    FORWARD = 0
}

вы можете получить описание с помощью кода следующим образом:

static void Main(string[] args)
{
    var it = InstallationType.FORWARD;
    var description = it.GetDescription();
    Console.WriteLine(description);
}