如何在C#中添加有关枚举类型的每个枚举值的元数据信息? 使用和测试输出改进仅使用一个属性

我想要一个带有扩展数据的枚举值列表。数据库将只保存一个与我的枚举值相对应的整数值,但是在代码中,我希望获得的信息不仅仅是枚举名称。

让我给你举个例子:

public enum Reason
{
    NotEnoughStock,// Valid = yes,Responsability = company,Text = There is not enough stock
    ProductNotAvailabe,// Valid = no,Text = Produc is not available
    PaymentNotDone,Responsability = client,Text = Payment is not done
    BlacklistedClient,Text = Client is black listed
    NotEnoughTime // Valid = yes,Text = There is not enough time
}

我该怎么做?除了枚举,我还应该使用其他东西吗?我喜欢枚举。

scorpiochenyr 回答:如何在C#中添加有关枚举类型的每个枚举值的元数据信息? 使用和测试输出改进仅使用一个属性

您可以:

  • 使用Attributes (C#);或
  • 创建通过类似this.id之类的返回额外信息的帮助器类。

对于' Text '值,您可以使用DescriptionAttribute。 对于其他两个,我认为您应该创建新属性。

Helper.GetExtraInfo(MyType val)

Get enum from enum attribute包含用于读取属性值的扩展方法。

,

在tymtam和Kevin的共同帮助下,我做到了:

void Main()
{
    Reason.NotEnoughStock.GetAttributeOfType<DescriptionAttribute>().Description;
    Reason.ProductNotAvailabe.GetAttributeOfType<ResponsabilityAttribute>().Responsability;
}

public enum Reason
{
    [Description("There is not enough stock")]
    [Valid(true)]
    [Responsability("company")]
    NotEnoughStock,[Description("Produc is not available")]
    [Valid(false)]
    [Responsability("company")]
    ProductNotAvailabe,[Description("Payment is not done")]
    [Valid(false)]
    [Responsability("client")]
    PaymentNotDone,[Description("Client is black listed")]
    [Valid(false)]
    [Responsability("client")]
    BlackListedClient,[Description("There is not enough time")]
    [Valid(true)]
    [Responsability("company")]
    NotEnoughTime 
}

public static class EnumHelper
{
    /// <summary>
    /// Gets an attribute on an enum field value
    /// </summary>
    /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
    /// <param name="enumVal">The enum value</param>
    /// <returns>The attribute of type T that exists on the enum value</returns>
    /// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
    public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute
    {
        var type = enumVal.GetType();
        var memInfo = type.GetMember(enumVal.ToString());
        var attributes = memInfo[0].GetCustomAttributes(typeof(T),false);
        return (attributes.Length > 0) ? (T)attributes[0] : null;
    }
}

public class ValidAttribute : Attribute
{
    public bool Valid;
    public ValidAttribute(bool valid) { Valid = valid; }
}

public class ResponsabilityAttribute : Attribute
{
    public string Responsability;
    public ResponsabilityAttribute(string responsability) { Responsability = responsability; }
}
,

您可以为枚举创建扩展方法,以便您仍然可以享受枚举并在Reason对象中获取数据。

var reason = Reason.NotEnoughStock.GetReasonInfo(ReasonData);

样品

internal class Program
{
    public static void Main(string[] args)
    {
        var reason = ReasonConstant.Reason.NotEnoughStock.GetReasonInfo(ReasonData);
    }
}

public static class ReasonUtils
{
    public static ReasonInfo GetReasonInfo(this ReasonConstant.Reason reason,Dictionary<ReasonConstant.Reason,ReasonInfo> reasonData)
    {
        if (reasonData == null)
            return null;
        if (!reasonData.ContainsKey(reason))
            return null;
        else
            return reasonData[reason];
    }
}

public class ReasonInfo
{
    public bool IsValid { get; set; }
    public string Responsability { get; set; }
    public string Text { get; set; }
}

public static class ReasonConstant
{
    public enum Reason
    {
        NotEnoughStock,// Valid = yes,Responsability = company,Text = There is not enough stock
        ProductNotAvailabe,// Valid = no,Text = Produc is not available
        PaymentNotDone,Responsability = client,Text = Payment is not done
        BlackListedClient,Text = Client is black listed
        NotEnoughTime // Valid = yes,Text = There is not enough time
    }
}
,

您的样本看起来可能是:

public enum Reason
{
    None = 0,Valid = 1,CompanyResponsible = 2,ClientResponsible = 4,Text = There is not enough stock
    [Description("There is not enough stock")
    NotEnoughStock = Valid | CompanyResponsible | 8,...

    // Valid = yes,Text = There is not enough time
    [Description("There is not enough time")
    NotEnoughTime = Valid | CompanyResponsible | 128,}

也许您可以排除一些单独的概念来替换| 8部分。

,

没有任何方法可以简单地实现目标。

您必须手动执行所需的行为。

您可能会考虑创建一个类,使其具有良好而适当的设计以及能够简单有效地使用它,因为实际上您询问如何创建以枚举值作为键的实例的字典。

如此:

  

Reason.cs

public enum Reason
{
  NotEnoughStock,ProductNotAvailabe,PaymentNotDone,BlackListedClient,NotEnoughTime
}

您可以创建此枚举:

  

Responsability.cs

public enum Responsability
{
  None,Company,Client
}

此类允许在实例中存储枚举的元数据,并提供在静态构造函数中初始化的枚举类型的所有元数据的静态列表:

  

ReasonMetaData.cs

using System.Collections.Generic;

public class ReasonMetaData
{

  static public Dictionary<Reason,ReasonMetaData> All { get; private set; }
  static ReasonMetaData()
  {
    All = new Dictionary<Reason,ReasonMetaData>();
    All.Add(
      Reason.NotEnoughStock,new ReasonMetaData(Responsability.Company,true,"There is not enough stock"));
    All.Add(
      Reason.ProductNotAvailabe,false,"Product is not available"));
    All.Add(
      Reason.PaymentNotDone,new ReasonMetaData(Responsability.Client,"Payment is not done"));
    All.Add(
      Reason.BlackListedClient,"Client is black listed"));
    All.Add(
      Reason.NotEnoughTime,"There is not enough time"));
  }
  static public ReasonMetaData Get(Reason reason)
  {
    if ( All.ContainsKey(reason) )
      return All[reason];
    else
      return null;
  }
  public Responsability Responsability { get; private set; }
  public bool Valid { get; private set; }
  public string Text { get; private set; }

  public override string ToString()
  {
    return $"Responsability = {Enum.GetName(typeof(Responsability),Responsability)}," +
           $"Valid = {( Valid ? "yes" : "no" )}" +
           $"Text = {Text}";
  }

  private ReasonMetaData()
  {
  }

  private ReasonMetaData(Responsability responsability,bool valid,string text)
  {
    Responsability = responsability;
    Valid = valid;
    Text = text;
  }
}

您还可以按照@RawitasKrungkaew的建议创建扩展方法:

  

ReasonMetadataHelper.cs

static public class ReasonMetadataHelper
{
  static public ReasonMetaData GetMetaData(this Reason reason)
  {
    return ReasonMetaData.Get(reason);
  }
}

使用和测试

static void Test()
{
  Console.WriteLine("Metadata of Reason.NotEnoughStock is:");
  Console.WriteLine(Reason.NotEnoughStock.GetMetaData());
  Console.WriteLine("");
  Console.WriteLine("Metadata of Reason.ProductNotAvailabe is:");
  Console.WriteLine(ReasonMetaData.Get(Reason.ProductNotAvailabe));
  Console.WriteLine("");
  Console.WriteLine("All metadata of Reason enum are:");
  foreach ( var item in ReasonMetaData.All )
    Console.WriteLine($"  {item.Key}: {item.Value}");
}

输出

Metadata of Reason.NotEnoughStock is:
Responsability = Company,Valid = yes,Text = There is not enough stock

Metadata of Reason.ProductNotAvailabe is:
Responsability = Company,Valid = no,Text = Product is not available

All metadata of Reason enum are:
  NotEnoughStock: Responsability = Company,Text = There is not enough stock
  ProductNotAvailabe: Responsability = Company,Text = Product is not available
  PaymentNotDone: Responsability = Client,Text = Payment is not done
  BlackListedClient: Responsability = Client,Text = Client is black listed
  NotEnoughTime: Responsability = Company,Text = There is not enough time

改进

您可以将此解决方案与属性混合使用,以通过解析枚举项的属性来自动创建列表:

如此:

  

ReasonAttributes.cs

public class ReasonResponsabilityAttribute : Attribute
{
  public Responsability Responsability { get; private set; }
  public ReasonResponsabilityAttribute(Responsability responsability)
  {
    Responsability = responsability;
  }
}

public class ReasonValidAttribute : Attribute
{
  public bool Valid { get; private set; }
  public ReasonValidAttribute(bool valid)
  {
    Valid = valid;
  }
}

public class ReasonTextAttribute : Attribute
{
  public string Text { get; private set; }
  public ReasonTextAttribute(string text)
  {
    Text = text;
  }
}
  

Reason.cs现在是:

public enum Reason
{

  [ReasonResponsability(Responsability.Company)]
  [ReasonValid(true)]
  [ReasonText("There is not enough stock")]
  NotEnoughStock,// ...
  ProductNotAvailabe,// ...
  PaymentNotDone,// ...
  BlackListedClient,// ...
  NotEnoughTime

}
  

ReasonMetadata.cs静态构造函数现在为:

using System.Reflection;

static ReasonMetaData()
{
  All = new Dictionary<Reason,ReasonMetaData>();
  var list = Enum.GetValues(typeof(Reason));
  foreach ( Reason reason in list )
  {
    var metadata = new ReasonMetaData();
    var memberinfo = reason.GetType().GetMember(Enum.GetName(typeof(Reason),reason));
    if ( memberinfo.Length == 1 )
    {
      var attributes = memberinfo[0].GetCustomAttributes();
      foreach ( Attribute attribute in attributes )
        if ( attribute is ReasonResponsabilityAttribute )
          metadata.Responsability = ( (ReasonResponsabilityAttribute)attribute ).Responsability;
        else
        if ( attribute is ReasonValidAttribute )
          metadata.Valid = ( (ReasonValidAttribute)attribute ).Valid;
        else
        if ( attribute is ReasonTextAttribute )
          metadata.Text = ( (ReasonTextAttribute)attribute ).Text;
    }
    All.Add(reason,metadata);
  }
}

仅使用一个属性

  

ReasonMetadataAttribute.cs

public class ReasonMetadataAttribute : Attribute
{
  public Responsability Responsability { get; private set; }
  public bool Valid { get; private set; }
  public string Text { get; private set; }
  public ReasonMetadataAttribute(Responsability responsability,string text)
  {
    Responsability = responsability;
    Valid = valid;
    Text = text;
  }
}
  

ReasonMetadata.cs静态构造函数现在为:

static ReasonMetaData()
{
  All = new Dictionary<Reason,reason));
    if ( memberinfo.Length == 1 )
    {
      var attributes = memberinfo[0].GetCustomAttributes();
      foreach ( Attribute attribute in attributes )
        if ( attribute is ReasonMetadataAttribute )
        {
          var metadataAttribute = (ReasonMetadataAttribute)attribute;
          metadata.Responsability = metadataAttribute.Responsability;
          metadata.Valid = metadataAttribute.Valid;
          metadata.Text = metadataAttribute.Text;
        }
    }
    All.Add(reason,metadata);
  }
}

用法:

public enum Reason
{
  [ReasonMetadata(Responsability.Company,"There is not enough stock")]
  NotEnoughStock,// ...
  NotEnoughTime
}
,

创建一个类来存储其他信息,例如ReasonDetail,然后使用Dictionary<Reason,ReasonDetail>并提供ReasonReasonDetail之间的映射

本文链接:https://www.f2er.com/3169080.html

大家都在问