2

I've got an enum class...

public enum LeadStatus : byte
{
    [Display(Name = "Created")] Created = 1,
    [Display(Name = "Assigned")] Assigned = 2,
    ....
}

Name of course is out-of-the-box. From MetaData...

namespace System.ComponentModel.DataAnnotations
{
    public sealed class DisplayAttribute : Attribute
    {
        ...
        public string Name { get; set; }
        ...
    }
}

Suppose I wanted my own custom Display Attribution, such as "BackgroundColor"...

[Display(Name = "Created", BackgroundColor="green")] Created = 1

I've seen a few other threads here that kinda dance around the issue, but the context is different enough that I can't make it work. I assume I need to create some sort of extension / override class, but I am not picturing this in my head.

Thanks!

Casey Crookston
  • 13,016
  • 24
  • 107
  • 193

3 Answers3

3

Having your own attribute.

public sealed class ExtrasDisplayAttribute : Attribute
{
    public string Name { get; set; }
    public string BackgroundColor { get; set; }
}

And this extension method.

namespace ExtensionsNamespace
{
    public static class Extensions
    {
        public static TAttribute GetAttribute<TAttribute>(Enum value) where TAttribute : Attribute
        {
            return value.GetType()
                .GetMember(value.ToString())[0]
                .GetCustomAttribute<TAttribute>();
        }
    }
}

Now you can extract attribute from enum like this.

using static ExtensionsNamespace.Extensions;

//...

var info = GetAttribute<ExtrasDisplayAttribute>(LeadStatus.Created);
var name = info.Name;
var bg = info.BackgroundColor;

//...

public enum LeadStatus : byte
{
    [ExtrasDisplay(Name = "Created", BackgroundColor = "Red")] Created = 1,
    [ExtrasDisplay(Name = "Assigned")] Assigned = 2,
}

If you want to still use the original attribute you can have that too. you should apply both attributes to single enum.

public enum LeadStatus : byte
{
    [Display(Name = "Created"), ExtrasDisplay(BackgroundColor = "Red")]Created = 1,
    [Display(Name = "Assigned")] Assigned = 2,
}

And extract each one you want.

var name = GetAttribute<DisplayAttribute>(LeadStatus.Created).Name;
var bg = GetAttribute<ExtrasDisplayAttribute>(LeadStatus.Created).BackgroundColor;
M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • having some trouble here.... BackgroundColor is not recognized. "The type or namespace BackgroundColor is not found." I get that when trying to use it as a Display Attribute in the enum's property – Casey Crookston Dec 21 '16 at 22:24
  • Where in my code / project do I put the extension method in your second code block? – Casey Crookston Dec 21 '16 at 22:25
  • I'm missing something here. In terns of the actual *.cs file... should I put both of these classes in the same literal file as the enum class? Or does it need to just be in the same namespace? – Casey Crookston Dec 21 '16 at 22:29
  • This solution will not work. This is not adding the `BackgroundColor` to the `DisplayAttribute` class as the OP asked. – CodingYoshi Dec 21 '16 at 22:31
  • @CodingYoshi -- yes, that is what I'm finding. – Casey Crookston Dec 21 '16 at 22:32
  • This only creates a whole other attribute derived from `attribute` and then it applies the attribute to an enum, then it reads the attribute for the enum using reflection. – CodingYoshi Dec 21 '16 at 22:33
  • If you are downvoting my answer, know that I never downvoted yours. I am simply saying that your solution will not work. Try this `[Display(Name = "Created", BackgroundColor="green")]`, there is no way you can do it. – CodingYoshi Dec 21 '16 at 22:45
  • I see your edits. But, as Yoshi said, this is still not working: [Display(Name = "Created", BackgroundColor="green")] – Casey Crookston Dec 21 '16 at 22:48
  • I am still trying here. Sure do appreciate your help! I'll report back soon. – Casey Crookston Dec 21 '16 at 22:53
  • @M.kazemAkhgary you are missing the point. Try and access one of the other properties of `DisplayAttribute` for example `AutoGenerateField` and you cannot. You have simply created a whole new `DisplayAttribute` which has nothing to do with the original one. – CodingYoshi Dec 21 '16 at 22:58
  • I thought that's what op wants. I see now. so if you want to use all the properties just copy everything needed from original class. will that work? I didn't see asp-net tag. @CodingYoshi – M.kazem Akhgary Dec 21 '16 at 23:03
  • @M.kazemAkhgary I am afraid that will not work because MVC uses this class to do a lot of magic for the UI and simply having the properties is not enough. Those properties need to have implementation. The point here is that this is not possible and as you can see, trying to force it, it is just roadblock after roadblock. Hope you see that :) – CodingYoshi Dec 21 '16 at 23:21
  • I see. that's why I unvoted. and sorry for being too confident, this was the final shot. @CodingYoshi – M.kazem Akhgary Dec 21 '16 at 23:24
  • 1
    @M.kazemAkhgary -- I want to thank you for your efforts! I DID get your solution to work, but I can also see that CodingYoshi has a valid point. Not using MVC's class is going to cause more trouble down the road. That being said, I sure do appreciate your time and effort. I up voted this. – Casey Crookston Dec 21 '16 at 23:25
2

public sealed class DisplayAttribute : Attribute is a sealed class and therefore you cannot inherit it and add other behavior or properties to it.

Below is my assumption but someone can chime in if they know why

And you may wonder why .NET developers made it sealed? I am wondering the same and my assumption is because each of the properties in DisplayAttribute are used to inject javascript, html etc. If they left it open, and you added a BackgroundColor property to it, what does that mean? What would that do in the UI?

CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
  • So, are you saying this isn't possible? If so, is there some kind of workaround? – Casey Crookston Dec 21 '16 at 22:33
  • there is no need to inherit or override this attribute. simply you can write your own attribute. my answer will work just fine. – M.kazem Akhgary Dec 21 '16 at 22:43
  • Only I'm not getting it to work. As I said in my comment under your answer, "BackgroundColor" is not recognized. – Casey Crookston Dec 21 '16 at 22:44
  • @CaseyCrookston I thought maybe if you wrapped the entire `DisplayAttribute` within a class which implements an interface with all the methods and properties of the `DisplayAttribute` and then used the decorator pattern...but then I figured when you use that in your UI, it will not work so I gave up entertaining that. So sorry I cannot think of anything but if I come up with anything I will be sure to ping you. – CodingYoshi Dec 21 '16 at 22:54
  • ok. so final work around for this would be to have two attributes applied to each member. that is possible like `[FistAttribute(...) , SecondAttrbute(...)]` and extract the one you want. @CaseyCrookston – M.kazem Akhgary Dec 21 '16 at 23:06
0

having concluded this this isn't possible, I went with another kind of solution. Not as tidy as I had hoped for originally, but it still gets the job done.

Methods inside enum in C#

Community
  • 1
  • 1
Casey Crookston
  • 13,016
  • 24
  • 107
  • 193