字符串变量读取属性的扩展方法

Extension method for string variable to read attribute

我有一个带有字符串常量的 class:

public static class Days 
{
    [Description("Wow!")]
    public const string Mon = "Hi!";
}

我发现 it is possible for enum to have an extension method to read Description attribute:

using System.ComponentModel;
public enum Days 
{    
    [Description("Wow!")]
    Mon
}

enum的扩展方法:

public static string ToName(this Enum value) 
{
    var attribute = value.GetAttribute<DescriptionAttribute>();
    return attribute == null ? value.ToString() : attribute.Description;
}

然后这样称呼它:

Days.Mon.ToName()

是否可以为 string 编写一个扩展方法以从 Mon 字符串变量的 Description 属性中获取 Wow! 并像那样调用字符串的扩展方法?

string description = Days.Mon.ToName(); // Output: "Wow!"

这不是那么简单,尽管有一些 hacky 的替代方案,我将在这个答案中解释其中最不 hacky 的(至少在我看来)。

首先,您无法将其作为 string 的扩展方法,原因很简单,因为无法从 string 中获取 FieldInfo 对象。但是,有一种方法可以从字段的类型和名称中获取 FieldInfo 对象。

您可以定义一个将这些作为参数并以这种方式获取属性的函数:

static string GetName<T>(string fieldName)
{
    var field = typeof(T).GetField(fieldName);
    if (field == null) // Field was not found
        throw new ArgumentException("Invalid field name", nameof(fieldName));

    var attribute = field.GetCustomAttribute<DescriptionAttribute>();
    return attribute == null ? (string) field.GetRawConstantValue() : attribute.Description;
}

请记住,这仅适用于类型为 string 的字段(如果该字段上没有 DescriptionAttribute)。如果您需要它与更多人一起工作,则需要对其进行调整。这也仅适用于 public 字段。同样,如果您需要它与更多人一起工作,则需要对其进行调整。

有了之后,你可以像这样使用它:

GetName<Days>(nameof(Days.Mon))

编辑:

如果您需要将它与静态 class 一起使用,您可以通过将其作为普通参数传递来绕过类型参数约束。以下函数执行此操作:

static string GetName(Type type, string fieldName)
{
    var field = type.GetField(fieldName);
    if (field == null) // Field was not found
        throw new ArgumentException("Invalid field name", nameof(fieldName));

    var attribute = field.GetCustomAttribute<DescriptionAttribute>();
    return attribute == null ? (string)field.GetRawConstantValue() : attribute.Description;
}

你可以这样使用:GetName(typeof(Days), nameof(Days.Mon))