【问题标题】:Extension method for string variable to read attribute字符串变量读取属性的扩展方法
【发布时间】:2022-01-05 05:52:56
【问题描述】:

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

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!"

【问题讨论】:

  • 我不明白你说“你可以像 X 一样称呼它”然后你又问“你能像 X 一样称呼它吗?” - 你是在问你是否可以做你刚才说你可以做的事情..?
  • 您不会从字符串的扩展方法中获取该信息。该 const 字符串不知道声明它的类。您可能会从 class Days 上的扩展方法中获得它,尽管这可能不是很有用
  • @CaiusJard 抱歉,如果我不清楚。我在问如何编写这样的扩展方法。 “你可以调用它”用于枚举类型。但是,我想要字符串类型的这种扩展方法。
  • 好的。你到底想做什么?你打算用这个做什么?
  • @CaiusJard 我有时需要阅读控制器属性中的“嗨!”。有时有必要阅读这个字符串变量的描述。我想避免使用Hi!Wow! 值创建两个字符串变量。

标签: c# asp.net-core reflection extension-methods asp.net-core-3.1


【解决方案1】:

这不是那么简单,尽管有一些 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&lt;Days&gt;(nameof(Days.Mon))

编辑

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

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))

【讨论】:

  • 但是我如何在不声明类名的情况下调用GetName&lt;Days&gt;(nameof(Days.Mon))
  • 什么意思?
  • 我的意思是,如果不创建包含此方法的类,就不可能调用“GetName”。或者你的意思是可以调用‘string.GetName(Days.Mon)’?你能举个例子吗?
  • 您必须为其创建一个类或将其放入现有类中。前面说了,不能放在string的扩展方法中。如果您需要帮助了解方法和类如何协同工作,here's the documentation for methods
  • 我更新了答案。
猜你喜欢
  • 2016-08-22
  • 2017-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 2017-04-17
  • 2011-07-09
  • 1970-01-01
  • 2017-09-22
相关资源
最近更新 更多