C# 根据值查找常量

C# 根据值查找常量,c#,struct,C#,Struct,我有一个第三方结构,由以下内容组成: [StructLayout(LayoutKind.Sequential, Size=1)] public struct BigBlueReasonCodes { public const int ABC_REASONCODE_DESCRIPTION001 = 1000; public const int ABC_REASONCODE_DESCRIPTION002 = 1005; public const int ABC_REASONC

我有一个第三方结构,由以下内容组成:

[StructLayout(LayoutKind.Sequential, Size=1)]
public struct BigBlueReasonCodes
{
    public const int ABC_REASONCODE_DESCRIPTION001 = 1000;
    public const int ABC_REASONCODE_DESCRIPTION002 = 1005;
    public const int ABC_REASONCODE_DESCRIPTION003 = 1010;
    public const int DEF_REASONCODE_DESCRIPTION004 = 2001;
    public const int DEF_REASONCODE_DESCRIPTION005 = 2010;
    public const int DEF_REASONCODE_DESCRIPTION006 = 2013;
    public const int GHI_REASONCODE_DESCRIPTION007 = 3050;
    public const int GHI_REASONCODE_DESCRIPTION008 = 3050;
    public const int GHI_REASONCODE_DESCRIPTION009 = 3052;
    public const string JKL_REASONCODE_DESCRIPTION010 = "XYZ";
    public const string GHI_REASONCODE_DESCRIPTION011 = "ST";


  static BigblueReasonCodes();
}
我试图根据原因代码和值查找原因描述字段名称,以便我的类可以执行以下操作:

string failureReason = GetReasonDescription(reasoncode);
值得一提的是,有些具有int值,有些具有字符串值。 我只担心那些具有int值的。
如果可能的话,我也只想要那些以GHI_u开头的,但不是什么大问题。

看起来你的整数常量应该是一个或多个枚举-这也允许整数之间的转换


您可以通过反射来实现这一点,但这比转换为枚举要慢。

看起来您的整数常量实际上应该是一个或多个枚举-这还允许与整数进行转换


您可以通过反射来实现这一点,但这比转换为枚举要慢。

如果将整数值填充到枚举中而不是常量中,您可以这样做

public enum BigBlueReasonCode
{
    ABC_REASONCODE_DESCRIPTION01 = 1000,
    ABC_REASONCODE_DESCRIPTION01 = 1005,
    ABC_REASONCODE_DESCRIPTION01 = 1010,
    DEF_REASONCODE_DESCRIPTION01 = 2001,
    DEF_REASONCODE_DESCRIPTION01 = 2010,
    DEF_REASONCODE_DESCRIPTION01 = 2013,
    GHI_REASONCODE_DESCRIPTION01 = 3050,
    GHI_REASONCODE_DESCRIPTION01 = 3051,
    GHI_REASONCODE_DESCRIPTION01 = 3052
}

var failureCode = Enum.GetName( reasoncode )

诚然,这段代码不会按原样工作,因为名称中有重复项,但它也不会编译为常量。

如果将整数值填充到枚举中而不是常量中,您可以这样做

public enum BigBlueReasonCode
{
    ABC_REASONCODE_DESCRIPTION01 = 1000,
    ABC_REASONCODE_DESCRIPTION01 = 1005,
    ABC_REASONCODE_DESCRIPTION01 = 1010,
    DEF_REASONCODE_DESCRIPTION01 = 2001,
    DEF_REASONCODE_DESCRIPTION01 = 2010,
    DEF_REASONCODE_DESCRIPTION01 = 2013,
    GHI_REASONCODE_DESCRIPTION01 = 3050,
    GHI_REASONCODE_DESCRIPTION01 = 3051,
    GHI_REASONCODE_DESCRIPTION01 = 3052
}

var failureCode = Enum.GetName( reasoncode )

诚然,这段代码不会按原样工作,因为名称中有重复项,但它也不会编译为常量。

您可以通过分析结构,使用反射来解决它:

public string GetReasonDescription(int reasonCode)
{
    return
        typeof(BigBlueReasonCodes)
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .Where(field => field.FieldType == typeof(int)) // Filter int values
            .Where(field => field.Name.StartsWith("GHI"))
            .Where(field => (int) field.GetValue(null) == reasonCode)
            .Select(field => field.Name).First(); // Assuming a field must exists
}
用法示例:

[Test]
public void GetReasonDescriptionTest()
{
    string reasonDescription = GetReasonDescription(3050);
    Assert.That(reasonDescription, Is.EqualTo("GHI_REASONCODE_DESCRIPTION007"));
}

您可以通过分析结构,使用反射来解决此问题:

public string GetReasonDescription(int reasonCode)
{
    return
        typeof(BigBlueReasonCodes)
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .Where(field => field.FieldType == typeof(int)) // Filter int values
            .Where(field => field.Name.StartsWith("GHI"))
            .Where(field => (int) field.GetValue(null) == reasonCode)
            .Select(field => field.Name).First(); // Assuming a field must exists
}
用法示例:

[Test]
public void GetReasonDescriptionTest()
{
    string reasonDescription = GetReasonDescription(3050);
    Assert.That(reasonDescription, Is.EqualTo("GHI_REASONCODE_DESCRIPTION007"));
}

+1:您可能需要使用GetFieldsBindingFlags.Public | BindingFlags.Static返回静态公共字段…@Reed Copsey,谢谢!它更好地描述了它,而且更安全。相应地更新了我的答案。完美!多谢。由于代码具有多个描述,我刚刚返回IEnumerable并显示所有匹配项。这些代码实际上是用来消费的,就像我猜rc==REASONCODE\u描述符一样。+1:您可能想使用GetFieldsBindingFlags.Public | BindingFlags.Static来返回静态的公共字段…@Reed Copsey,谢谢!它更好地描述了它,而且更安全。相应地更新了我的答案。完美!多谢。由于代码具有多个描述,我刚刚返回IEnumerable并显示所有匹配项。这些代码实际上是用来消费的,比如我猜rc==REASONCODE\u描述符。我看到它们很好,有一个值意味着多个东西,所以3050可能意味着GHI\u007和GHI\u008,伙计哦,伙计。我看到它们很好,有一个值意味着多个东西,所以3050可能意味着GHI\u007和GHI\u008,伙计哦,伙计。枚举不存在了,因为同一个代码有多重含义。@Joel。除了现有代码之外,是否使用枚举或常量应该是一个问题。正如不能有两个同名的常量一样,也不能有两个同名的枚举。枚举已退出,因为同一代码具有多重含义。@Joel。除了现有代码之外,是否使用枚举或常量应该是一个问题。正如不能有两个同名的常量一样,也不能有两个同名的枚举。我假定此上下文中的reasonCode是数字。也就是说,用户传入了Enum.GetName2010。请在注释前面加上@Steve,以便通知我。如果它是非标志枚举,并且设置为其定义的值之一,则reasoncode.ToString返回名称。如果它不是定义的值之一,则返回数字。对于标志枚举,它实际上在返回以逗号分隔的选定选项列表方面做得非常好。也就是说,用户传入了Enum.GetName2010。请在注释前面加上@Steve,以便通知我。如果它是非标志枚举,并且设置为其定义的值之一,则reasoncode.ToString返回名称。如果它不是定义的值之一,则返回数字。对于标志枚举,它实际上在返回以逗号分隔的选定选项列表方面做得非常好。