Home > database >  Extension method for string variable to read attribute
Extension method for string variable to read attribute

Time:11-29

I have a class with string constants:

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

I've found that it is possible for enum to have an extension method to read Description attribute:

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

An extension method for enum:

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

And call it like that:

Days.Mon.ToName()

Is it possible to write an extension method for string to get Wow! from Description attribute of Mon string variable and call extension method for string like that?

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

CodePudding user response:

It's not quite that simple, although there are a few hacky alternatives, the least hacky of which (in my opinion at least) I will be explaining in this answer.

First off, there's no way you can make it an extension method of string, simply because there's no way to get a FieldInfo object from a string. There is however, a way to get a FieldInfo object from the type and name of the field.

You can define a function that takes these as arguments and gets the attribute that way:

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;
}

Keep in mind that this will only work properly for fields with a type of string (if there is no DescriptionAttribute on the field anyway). If you need it to work with more, it will need to be adapted to do so. This will also only work with public fields. Again, if you need it to work with more it will need to be adapted to do so.

After you have that, you can use it like so:

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

EDIT:

If you need to use this with a static class, you can get around the type argument constraint by passing it as a normal argument. The following function does that:

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;
}

You can use call this like so: GetName(typeof(Days), nameof(Days.Mon))

  • Related