可移植类库中的System.ComponentModel.DescriptionAttribute

24

我在枚举类型中使用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
据我所知,System.ComponentModel.DescriptionAttribute 实际上是 System.dll 的一部分,这应该已经是您项目的引用了。您只是缺少了 using 指令吗? - olydis
不,我已经使用了(从以前的dll中复制粘贴的类)。你是对的,system.componentmodel在那里,只是似乎无法使用description。 - Crudler
3个回答

28

由于便携式类库不支持 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;
    }

听起来是个不错的解决方案。那么在我的方法tr中检索它,我只需要用DisplayAttribute替换DescriptionAttribute吗? - Crudler
1
这个也适用于像DescriptionAttribute一样的ToString()吗? - gregsdennis
那么这个功能对于同时针对Xamarin API的PCL不可用吗?当Xamarin已经有DescriptionAttribute时,这是一个失败的#操作。-https://developer.xamarin.com/api/type/System.ComponentModel.DescriptionAttribute/ - George Birbilis
看起来这段代码在某些PCL配置文件中无法工作。例如,我使用Profile111 / .NET 4.5和命名空间System.ComponentModel.DataAnnotations以及代码value.GetType().GetField在那里不可用。我使用了另一段代码,我在下面发布了它。 - Bogdan Kanteruk
不知道微软是否正在(或计划)通过NuGet提供缺失的内容,以便使用单独的PCL库。 - George Birbilis
显示剩余4条评论

16

是否可以在可移植类库中使用某个属性,这取决于您选择的框架 - 仅获得严格交集。然而,可能有一种情况是其中一个目标框架中根本不存在该属性。此时,添加您自己的选项就可以了 - 这样您就知道它可用。例如:

[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
尝试使用以下代码在可移植库中检索枚举属性:
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>();
    }
}
更新: 同时,您需要声明新属性(看起来像是PCL中没有的DescriptionAttribute),例如下面这样:
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);
}

问题是如何在PCL中声明属性。 - George Birbilis

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