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 говорит мне, что я уже ссылался на все.
Спасибо
Ответы
Ответ 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);
}