【问题标题】:How to decorate enum with attribute in c#如何在 C# 中用属性装饰枚举
【发布时间】:2023-03-30 07:40:01
【问题描述】:

我的解决方案中有一个关于帮助程序库的枚举。 例如

 public enum MyEnum 
 {  
  First,
   Second 
  }

我想在另一个项目中使用 MyEnum。我想在每个项目中用自己的属性装饰这个枚举,如下所示:

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

如何用自己的本地属性装饰另一个库中的枚举?

【问题讨论】:

  • 所以你在项目A中有一个枚举,你想在项目B中使用它但只在项目B中使用属性?
  • @Darren 是的,我想在项目 B 中使用来自 A 的枚举,特定属性仅在项目 B 中使用
  • 那么不,你不能像RB所说的那样做。

标签: c# design-patterns enums


【解决方案1】:

你不能做你所描述的——你能做的最好的就是创建一个使用相同值集的新 Enum。然后,无论何时使用它,您都需要强制转换为“真实”枚举。

您可以使用 T4 模板或类似的模板为您生成属性枚举 - 这样会更安全,因为它很容易映射错误的值,从而产生一些非常微妙的错误!

Linqpad 查询

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);   
}

【讨论】:

    【解决方案2】:

    属性是代码的编译时添加(元数据)。使用编译后的代码程序集时不能修改它们。
    (或者如果你是一个顽固的低级 IL 向导,也许你可以,但我当然不是......)

    如果您的 enum 值需要在各个地方修改或参数,那么您应该考虑其他解决方案,例如Dictionary 甚至是数据库表。

    例如使用Dictionary:

    var values = new Dictionary<MyEnum, int>()
    {
        { MyEnum.First, 25 },
        { MyEnum.Second, 42 }
    };
    var valueForSecond = values[MyEnum.Second]; // returns 42
    

    【讨论】:

      【解决方案3】:

      你可以做这样的事情,但是会很乏味。
      这个想法是在您将枚举导入新项目时使用您的项目设置来允许更改。

      首先,您需要 2 个属性:

      // 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; }
      }
      

      那么,这个方法:

      // 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)];
      }
      

      我没有检查类型是否正确,即使它找到任何属性也没有。你必须这样做,否则如果你没有提供正确的类型,你会得到一个异常。

      现在,您的枚举将如下所示:

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

      最后,在您的项目设置中,您必须添加与枚举中的成员数量一样多的行。
      您必须使用与 EnumAttribute 的参数相同的模式来命名每一行。这里是“Key{0}”,所以:

      1. Key0:您的第一个值
      2. Key1:你的第二个值
      3. 等等……

      像这样,您只需更改设置值(NOT THE KEY)即可导入您的枚举并将您的属性更改为另一个项目。

      用法:

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

      它将返回“您的第一个值”。

      【讨论】:

      • 问题不在于如何定义可以与 Enums 一起使用的属性。
      • @PeterB,感谢您的反馈。这个问题首先不清楚。这就是为什么我做了这个简短的回答。我现在正在寻找其他东西。
      • @PeterB,如果您不介意看一下,我对我的帖子进行了重大更新。我会很高兴:)
      • 老实说它看起来相当复杂,而且它需要在设置中重复枚举值作为字符串键,使其编译不安全。我不会用这个。
      • @PeterB,同意。目的是表明即使有很多缺点,也可以为少数专业人士做。我宁愿像你一样使用字典,而不是那样。但即便如此,创造它也很有趣,而且有一天它可能对某人有用。感谢您的反馈。
      猜你喜欢
      • 2012-07-28
      • 2022-11-28
      • 2013-05-11
      • 2018-02-04
      • 1970-01-01
      • 2020-04-09
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多