tags:

views:

70

answers:

3

I have a 3rd party struct that is comprised of the following:

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

I am trying to look up the reason description(the field name) based on the reason code(the value) so my class can do someting like:

string failureReason = GetReasonDescription(reasoncode);

Somethings of mention are some have int values and some have string values. I am only worried about the ones with int values. I also only want the ones that start with GHI_ if possible but not a big deal.

+4  A: 

Looks like your integer consts should really be an enumeration (or several enumerations) - this will also allow conversion to and from integers.

You could do this via reflection, but it will be slower than converting to enums.

Oded
enumeration is out, because the same code has multiple meanings.
Joel Coehoorn
@Joel. It should be a push as to whether you use an enum or constant except for existing code. Just as you cannot have two constants with the same name, you cannot have two enums with the same name.
Thomas
+1  A: 

If you stuffed the integer values into enum instead of constants, you could do

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 )

(Granted, as is this code will not work as is because you have duplicates in the names but it wouldn't compile as constants either.)

Thomas
Why not `reasoncode.ToString()`?
Steven Sudit
I'm presuming that "reasonCode" in this context is numeric. I.e, the user passed in Enum.GetName(2010).
Thomas
@Thomas, please prefix comments with @Steve so that I'm notified. If it's a non-flag enum and it's set to one of its defined values, then reasoncode.ToString() with return the name. If it's not one of the defined values, it returns the number. For flag enums, it actually does a surprisingly good job of returning a comma-delimited list of selected options.
Steven Sudit
+6  A: 

You can solve it using reflection, by analyzing the struct:

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
}

Usage example:

[Test]
public void GetReasonDescriptionTest()
{
    string reasonDescription = GetReasonDescription(3050);
    Assert.That(reasonDescription, Is.EqualTo("GHI_REASONCODE_DESCRIPTION007"));
}
Elisha
+1: You might want to use GetFields(BindingFlags.Public|BindingFlags.Static) to just return the static, public fields...
Reed Copsey
@Reed Copsey, thanks! It describes it better and it's safer. Updated my answer accordingly.
Elisha
Perfect! Thanks much. Due to a code having multiple description I just returned IEnumerable<String> and show all that match.The codes were actually made to consume like if (rc==REASONCODE_DESCRIPTON) I guess.
Phil Langeberg