0

I have an enum on helper library in my solution. For example

 public enum MyEnum 
 {  
  First,
   Second 
  }

I want to use MyEnum in a few another project. I want to decorate this enum in each project with own attribute like this:

public enum MyEnum 
 { 
 [MyAttribute(param)] 
 First,
 [MyAttribute(param2)]
 Second 
}

How to decorate enum from another library with own local attribute?

ElConrado
  • 1,477
  • 4
  • 20
  • 46

3 Answers3

2

You can't do what you've described - the best you can do is to create a new Enum that uses the same set of values. You will then need to cast to the "real" enum whenever you use it.

You could use T4 templates or similar to generate the attributed enum for you - it would be much safer that way as it would be very easy to map the wrong values, making for some very subtle bugs!

Linqpad Query

enum PrimaryColor
{
    Red,
    Blue,
    Green
}

enum AttributedPrimaryColor
{
    [MyAttribute]
    Red = PrimaryColor.Red,
    [MyAttribute]
    Blue = PrimaryColor.Blue,
    [MyAttribute]
    Green = PrimaryColor.Green
}

static void PrintColor(PrimaryColor color)
{
    Console.WriteLine(color);
}

void Main()
{
    // We have to perform a cast to PrimaryColor here.
    // As they both have the same base type (int in this case)
    // this cast will be fine.
    PrintColor((PrimaryColor)AttributedPrimaryColor.Red);   
}
RB.
  • 36,301
  • 12
  • 91
  • 131
1

Attributes are compile-time additions (metadata) to code. You can not modify them when using the compiled code assembly.
(Or perhaps you could if you are a diehard low-level IL wizard, but I certainly am not...)

If your enum values require modification or parameters at various places, then you should consider other solutions, e.g. a Dictionary or even a Database Table.

E.g. using a Dictionary:

var values = new Dictionary<MyEnum, int>()
{
    { MyEnum.First, 25 },
    { MyEnum.Second, 42 }
};
var valueForSecond = values[MyEnum.Second]; // returns 42
Peter B
  • 22,460
  • 5
  • 32
  • 69
-3

You can do something like this, but it will be tedious.
The idea is to use your project settings to allow the change when you import the enum in a new project.

First, you will need 2 attributes:

// This one is to indicate the format of the keys in your settings
public class EnumAttribute : Attribute
{
    public EnumAttribute(string key)
    {
        Key = key;
    }

    public string Key { get; }
}

// This one is to give an id to your enum field
[AttributeUsage(AttributeTargets.Field)]
public class EnumValueAttribute : Attribute
{
    public EnumValueAttribute(int id)
    {
        Id = id;
    }
    public int Id { get; }
}

Then, this method:

// This method will get your attribute value from your enum value
public object GetEnumAttributeValue<TEnum>(TEnum value)
{
    var enumAttribute = (EnumAttribute)typeof(TEnum)
        .GetCustomAttributes(typeof(EnumAttribute), false)
        .First();
    var valueAttribute = (EnumValueAttribute)typeof(TEnum).GetMember(value.ToString())
        .First()
        .GetCustomAttributes(typeof(EnumValueAttribute), false)
        .First();
    return Settings.Default[String.Format(enumAttribute.Key, valueAttribute.Id)];
}

I did not check if the type is correct, not even if it finds any attributes. You will have to do it, otherwise you will get an exception if you don't provide the right type.

Now, your enum will look like that:

[Enum("Key{0}")]
public enum MyEnum
{
    [EnumValue(0)] First,
    [EnumValue(1)] Second
}

Finally, in your project settings, you will have to add as many lines as the number of members in your enum.
You will have to name each line with the same pattern as the parameter given to EnumAttribute. Here, it's "Key{0}", so:

  1. Key0: Your first value
  2. Key1: Your second value
  3. etc...

Like this, you only have to change your settings values (NOT THE KEY) to import your enum and change your attributes to a project to another.

Usage:

/*Wherever you put your method*/.GetEnumAttributeValue(MyEnum.First);

It will return you "Your first value".

romain-aga
  • 1,441
  • 9
  • 14
  • The question is not about how to define an attribute that can be used with Enums. – Peter B Oct 20 '16 at 12:20
  • @PeterB, Thanks for your feedback. The question was unclear first. That's why I did this short answer. I'm looking for something else now. – romain-aga Oct 20 '16 at 12:24
  • @PeterB, I made a huge update to my post, if you don't mind to take a look. I will be pleased :) – romain-aga Oct 20 '16 at 13:03
  • To be honest it looks rather complicated, and it requires repetition of enum values as string keys in Settings, making it not compile safe. I would not use this. – Peter B Oct 21 '16 at 06:54
  • @PeterB, Agreed. The purpose was to show that it is possible to do, even if it has a lot of cons, for few pros. I would rather use a dictionary like you did, instead of that. But even, it was interesting to create and it might be useful for someone, one day. Thanks for the feedback. – romain-aga Oct 21 '16 at 08:39