简体   繁体   中英

Custom Attribute - get value of underlying enum

I'm not sure of all of the correct terminology for what I am trying to do, so I will just dive in with some code.

Current Setup

public enum NavigationLinks
{
    [FriendlyName("System Dashboard")]
    SystemDashboard,
    [FriendlyName("Trading Dashboard")]
    TradingDashboard,
}

public class UINameAttribute : Attribute
{
    public string Value { get; private set; }

    public UINameAttribute(string Value)
    {
        this.Value = Value;
    }
}

What I would like

public enum NavigationLinks
{
    [FriendlyName]
    SystemDashboard,
    [FriendlyName]
    TradingDashboard,
}

public class UINameAttribute : Attribute
{
    public string Value { get; private set; }

    public UINameAttribute(string Value)
    {
        this.Value = Value;
    }

    public UINameAttribute()
    {
        string AttributedValue = this.AttributedObject.ToString();
        // Take the value of the attribute and add a space in between the camel case.
    }
}

Basically - I was wondering if I can access the underlying 'thing' that the attribute is on from within the constructor of the attribute -

Thanks in advanced! William

No, you can't access attributed member from within the attribute's constructor.

But why do that anyway, if you already have a logic how to resolve friendly name from enum value.

public enum NavigationLinks
{
    SystemDashboard,
    TradingDashboard,
}

public static class Program
{
    private static string ToFriendlyName(string defaultName)
    {
        var sb = new StringBuilder(defaultName);

        for (int i = 1; i < sb.Length; ++i)
            if (char.IsUpper(sb[i]))
            {
                sb.Insert(i, ' ');
                ++i;
            }

        return sb.ToString();
    }

    public static void Main(string[] args)
    {
        var value = NavigationLinks.SystemDashboard;

        var friendlyName = ToFriendlyName(value.ToString());
    }
}

In addition to Stipo's approach you can also write an extension method to get the name, something like this:

public static class NavigationLinksExtension
{
    public static string GetFriendlyName(this NavigationLinks navLink)
    {
        string tmpName = navLink.ToString();
        tmpName = Regex.Replace(tmpName, "(?<=[a-z])([A-Z])", " $1"); // insert space
        return tmpName;
    }
}

Then you can simply access the value:

NavigationLinks nl = NavigationLinks.TradingDashboard;
string nlFriendlyName = nl.GetFriendlyName();

An attribute can't (directly) get access to the thing it is describing. If you want ToString() to be the default and only override it occasionally, you would be better off with a helper function (eg GetFriendlyName) that defaults to ToString(), but replaces it with the value in a FriendlyName attribute should one exist.

Please try the following:

var inputString = NavigationLinks.SystemDashboard;
Regex.Replace(inputString, "([A-Z][a-z0-9]+)+", "$1$2");

Use the DescriptionAttribute (or create a custom attribute), then, using Reflection to get the value:

Create the class EnumDescriptions (using System.ComponentModel and System.Reflection):

public class EnumDescriptions
{
    public static string StringValueOf(Enum value)
    {
        FieldInfo fieldInfo = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

        return attributes[0].Description;
    }

And put Description in the Enum:

    public enum Animals
    {
        [Description("System Dashboard")]
        SystemDashboard,
        [Description("Trading Dashboard")]
        TradingDashboard,
    } 

To get the values:

    static void Main(string[] args)
    {
        Console.WriteLine(EnumDescriptions.StringValueOf(Animals.SystemDashboard));
        Console.WriteLine();
        Console.WriteLine(EnumDescriptions.StringValueOf(Animals.TradingDashboard));
        Console.Read();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM