Main Site Documentation

Reflecting Enums in MF


#1

I’m trying to store the analogue port to use for a temperature sensor in an xml config file on an SD card, however when I try to pull the field for the value, it comes up null.

It turns out that FEZ_Pin.AnalogIn only has one field (rather than 6). This is running on a PandaII.


string port="An0";
Type pinEnumType = typeof(FEZ_Pin.AnalogIn);
FieldInfo field = pinEnumType.GetField(port);
Cpu.Pin value = (Cpu.Pin)field.GetValue(pinEnumType);

This would work as expected on full .Net or CF (not that you would do it this way after .net 1.1…) however it just doesn’t work on NetMF.

Any ideas how I can get the value of the a specified Enum field in NetMF?


#2

// Type: GHIElectronics.NETMF.FEZ.FEZ_Pin
// Assembly: FEZPanda_II_GHIElectronics.NETMF.FEZ, Version=4.1.5.0, Culture=neutral
// Assembly location: C:\Program Files\GHI Electronics\GHI NETMF v4.1 SDK\Assemblies\FEZPanda_II_GHIElectronics.NETMF.FEZ.dll

public static class FEZ_Pin
{
        public enum AnalogIn : byte
        {
            An0 = 0,
            An1 = 1,
            An2 = 2,
            An3 = 3,
            An4 = 4,
            An5 = 5,
        }

        public enum AnalogOut : byte
        {
            An3 = 0,
        }

        public enum Digital : byte
        {
            LDR = 0,
            Di41 = 1,
            Di5 = 2,
            Di37 = 3,
            MOD = 4,
            Di39 = 5,
            Di38 = 6,
            Di6 = 7,
            Di36 = 8,
            Di35 = 10,
            Di43 = 11,
            Di34 = 12,
            Di33 = 13,
            Di32 = 14,
            Di7 = 15,
            Di30 = 16,
            Di31 = 17,
            Di1 = 18,
            Di4 = 19,
            Di0 = 20,
            Di46 = 21,
            An3 = 22,
            Di8 = 23,
            An2 = 24,
            Di9 = 25,
            An1 = 26,
            An0 = 28,
            An4 = 29,
            Di3 = 31,
            An5 = 32,
            Di2 = 33,
            Di10 = 35,
            Di40 = 38,
            Di42 = 39,
            Di12 = 40,
            Di11 = 41,
            Di13 = 42,
            SD_Detect = 43,
            Di21 = 51,
            Di20 = 52,
            Di23 = 53,
            Di22 = 54,
            Di25 = 55,
            Di24 = 56,
            Di27 = 57,
            Di26 = 58,
            Di29 = 59,
            Di28 = 60,
            Di51 = 61,
            Di50 = 62,
            Di49 = 63,
            Di48 = 64,
            Di47 = 65,
            Di45 = 66,
            Di44 = 67,
            Di52 = 68,
            LED = 69,
        }

        public enum Interrupt : byte
        {
            LDR = 0,
            Di41 = 1,
            Di5 = 2,
            Di37 = 3,
            MOD = 4,
            Di39 = 5,
            Di38 = 6,
            Di6 = 7,
            Di36 = 8,
            Di35 = 10,
            Di43 = 11,
            Di34 = 12,
            Di32 = 14,
            Di7 = 15,
            Di30 = 16,
            Di1 = 18,
            Di4 = 19,
            Di0 = 20,
            An3 = 22,
            An2 = 24,
            An1 = 26,
            An0 = 28,
            Di3 = 31,
            Di2 = 33,
            Di40 = 38,
            Di42 = 39,
            Di12 = 40,
            Di11 = 41,
            Di13 = 42,
            SD_Detect = 43,
        }

        public enum PWM : byte
        {
            Di10 = 1,
            Di9 = 2,
            Di8 = 3,
            MOD = 4,
            Di5 = 5,
            Di6 = 6,
        }
}


#3

So instead of saving a string ‘An0’ save digit ‘0’. Then recreate it like this:


byte port = 0;
Cpu.Pin value = (Cpu.Pin) port;


#4

Thankyou for your response Gralin, I’m hoping to store the pin name (hence the post), as the user needs to be able to configure this and other pins for use. Using the Di and An pin format as is on the Panda II PCB is much preferred.

I’m not interested in doing a hard coded lookup against an array of values taken from the reflected values either. This is about as un-elegant a solution as is possible heh.

Reflection appears to be the best way to do this, hence my post here. I’m intrigued by the difference in the way an Enum reflects from NetMF to Full/CF. Even the full framework’s internal code uses the field lookup route as I have posted here - I had a look to see if there was a better way of doing it in the full framework.

The full framework has static methods on the Enum class which facilitate what I’m hoping to achieve however these use the same way of doing the lookup as my code in the first post.


#5

If you want to do that, you can check that the last character…


Cpu.Pin value = (Cpu.Pin)((AnalogIn)((byte)userInput[2] - 48));

As long as the user input is greater than 3 characters long and character 2 (third position) is a number, this will give you the pin.


#6

Assemblies in NETMF (PF files) are a simplified version of the full DLL and do not have everything.


#7

Silic0re, this won’t work on digital pins.

Gus, is this to say that there is no way to reflect an enum?


#8

    [Serializable]
    public abstract class Enum : ValueType
    {

        public override String ToString()
        {
            Type eT = this.GetType();
            FieldInfo fi = eT.GetField("value__");
            object obj = fi.GetValue(this);

            return obj.ToString();
        }

    }

That’s the entire Enum class in C#'s MF framework. You can see it uses reflection to get the field value, so I’m not sure why your first code listing wouldn’t work…

The only other thing I can think of is a giant switch statement…


#9

Running this code:



        private static void AnalogInDebug()
        {
            Type pinEnumType = typeof(FEZ_Pin.AnalogIn);
            FieldInfo[] fields = pinEnumType.GetFields();

            Debug.Print("Number of fields in AnalogIn: " + fields.Length);

            foreach (FieldInfo field in fields)
            {
                Debug.Print("Field: " + field.Name + " = " + field.GetValue(new FEZ_Pin.AnalogIn()));
            }

            MethodInfo[] methods = pinEnumType.GetMethods();

            Debug.Print("Number of methods in AnalogIn: " + methods.Length);

            foreach (var method in methods)
            {
                Debug.Print("Method: " + method.Name);
            }
        }

Gives:

Number of fields in AnalogIn: 1
Field: value__ = 0
Number of methods in AnalogIn: 8
Method: ToString
Method: Equals
Method: ToString
Method: Equals
Method: GetHashCode
Method: GetType
Method: Equals
Method: ReferenceEquals

And the same for the Digtal and other enums.

If you get value on a specific Enum field:


Debug.Print("Field: " + field.Name + " = " + field.GetValue(FEZ_Pin.Digital.Di7));

It gives you:
Field: value__ = 15

Therefore, I can only assume that Enums are implemented in a totally different fashion in .net MF to any other .net flavour.

It’s easy enough to create an instance of the enum, but not for the field you want… I guess i’ll have to just store the Cpu.Pin number… what a pain.


#10

Indeed, they decided to not include the names in the binary to save some space.

I’ve asked this question here before, and william came up with a greate switch-case solution I’m using right now :slight_smile:

http://www.tinyclr.com/forum/1/2313/

and

http://www.tinyclr.com/forum/1/1395/