3

My project has this BookDetails attribute:

public enum Books
{
    [BookDetails("Jack London", 1906)]
    WhiteFange,

    [BookDetails("Herman Melville", 1851)]
    MobyDick,

    [BookDetails("Lynne Reid Banks", 1980)]
    IndianInTheCupboard

}

and code for attribute here:

[AttributeUsage(AttributeTargets.Field)]
public class BookDetails : Attribute
{
    public string Author { get; }
    public int YearPublished { get; }

    public BookDetails(string author, int yearPublished)
    {
        Author = author;
        YearPublished = yearPublished;
    }
}

How do I get the author for a given Book?

Tried this messy code but it didn't work:

 var author = Books.IndianInTheCupboard.GetType().GetCustomAttributes(false).GetType().GetProperty("Author");  // returns null

Thanks, there's got to be a better way than what I was trying above.

H.B.
  • 166,899
  • 29
  • 327
  • 400
RayLoveless
  • 19,880
  • 21
  • 76
  • 94

3 Answers3

5

Since the attribute is attached to an enum field, you should apply GetCustomAttribute to FieldInfo:

var res = typeof(Books)
    .GetField(nameof(Books.IndianInTheCupboard))
    .GetCustomAttribute<BookDetails>(false)
    .Author;

Since attribute type is known statically, applying generic version of the GetCustomAttribute<T> method yields better type safety for getting the Author attribute.

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The code in your "Demo" link works but the code in the snippet does not. I had an error with "nameof" method. The assingment to the variable res works in the demo code with this line: var res = typeof(Books).GetField("IndianInTheCupboard").GetCustomAttribute(false).Author; – C_Sutt Jun 27 '23 at 21:09
  • 1
    @C_Sutt [The modified version of the demo](https://ideone.com/DwUoEF) works fine. – Sergey Kalinichenko Jun 28 '23 at 03:03
  • Woops, I copied the wrong line. I meant the one in your post, not the demo. var res = typeof(Books) .GetField(nameof(Books.IndianInTheCupboard)) .GetCustomAttribute(false) .Author; – C_Sutt Jun 28 '23 at 20:12
1

Your solution does not work because you are trying to find attribute of the type Books, but not attribute of the enumeration element. It works.

var fieldInfo = typeof(Books).GetField(Books.IndianInTheCupboard.ToString());
var attribute = fieldInfo.GetCustomAttributes(typeof(BookDetails), false).FirstOrDefault() as BookDetails;
var author = attribute.Author;

If you need to get values of this attribute often you can write extension for it.

public static class EnumExtensions
{
    public static BookDetails GetDescription(this Books value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());
        var attribute = fieldInfo.GetCustomAttributes(typeof(BookDetails), false).FirstOrDefault() as BookDetails;

        return attribute;
    }
}
Valerii
  • 2,147
  • 2
  • 13
  • 27
0

Already by answered Bryan Rowe. Replication of his solution accord your example:

    var type = typeof(Books);
    var memInfo = type.GetMember(Books.IndianInTheCupboard.ToString());
    var attributes = memInfo[0].GetCustomAttributes(typeof(BookDetails), false);
    var description = ((BookDetails)attributes[0]).Author;
4D1C70
  • 490
  • 3
  • 10