-1

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!"
Learner
  • 417
  • 6
  • 24
  • I didn't understand the bit where you said "you can call it like X" and then you asked "can you call it like X?" - you're asking the whether you can do the thing you just said you can do..? – Caius Jard Nov 27 '21 at 17:02
  • 1
    You're not going to get that information from an extension method on string. That const string has no idea about the class that declares it. You could likely get it from an extension method on `class Days`, though that likely isn't very useful – Flydog57 Nov 27 '21 at 17:04
  • @CaiusJard sorry for if I was unclear. I am asking how to write such extension method. “You can call it” is for enum type. However, I want such extension method for string type. – Learner Nov 27 '21 at 17:55
  • Ok. What are you actually trying to do? What are you going to use this for? – Caius Jard Nov 27 '21 at 17:58
  • @CaiusJard I need to read sometimes ``Hi!` in attribute of controller. Sometimes it is necessary to read description of this string variable. And I want to avoid to create two string variables with `Hi!` and `Wow!` values. – Learner Nov 27 '21 at 18:33
  • @Flydog57 maybe is it possible to write an extension method for `object` type and use it for `string`? – Learner Nov 27 '21 at 18:38
  • You can write about extension method for object (unless that's been very recently added to the language) – Flydog57 Nov 27 '21 at 19:19
  • *And I want to avoid to create two string variables with Hi! and Wow! values* - because.. what? the attributes are "free"? If anything it seems like this should be in a localization system – Caius Jard Nov 28 '21 at 01:20

1 Answers1

0

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 this like so: GetName(typeof(Days), nameof(Days.Mon))

Jesse
  • 1,386
  • 3
  • 9
  • 23
  • But how I can call `GetName(nameof(Days.Mon))` without declaring class name? – Learner Nov 27 '21 at 18:34
  • What do you mean? – Jesse Nov 27 '21 at 18:46
  • I mean that it is not possible to call ‘GetName’ without creating a class that contains this method. Or do you mean that it is possible to call ‘string.GetName(Days.Mon)’? Could you show please an example of usage? – Learner Nov 27 '21 at 22:17
  • You would have to create a class for it or put it in an existing class. As I said before, it's not possible to put it in an extension method of `string`. If you need help figuring out how methods and classes work together, [here's the documentation for methods](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/methods). – Jesse Nov 27 '21 at 23:44
  • Thanks! I've tried your code. However, it says `'Days': static types cannot be used as type arguments`. Could you please say how it can be solved? – Learner Nov 28 '21 at 13:49