enum.Parse again

Hello guys,
does anyone know of way to get an Enum Type by it’s string name? if not do you have any alternative ways of doing this:
i checked the forum and saw some old posts about a year ago or so and was wondering if the latest version of netMf includes anything new, in this regards.

Why you ask i need this:
because I’m trying to rebuild an Object at run-time from a string… Json to Object…


public enum myEnumType
{
   None,
   test,
   cool,
}

myObject.Type = (myEnumType)Enum.Parse(typeof(myEnumType), "test");


Please let me know of any ideas on how to achieve this or any other ways of doing similar things.

thanks.

You could do something like this:

public enum myEnumType:int
{
   None = 0,
   test = 1,
   cool = 2,
}

myEnumType aux = myEnumType.test;
int value = (int)aux;
myObject.Type = (myEnumType)value;

Still the same. You need to implement your own method that will return enum value for its string value.

Thank you guys for your replies.
@ godFather89:
the whole point behind doing it my way is to pass the Enum as a string…so hard coding the enum as in your example will not work for me… unless i combine it with a switch statement, which will make the code hard to maintain down the road, since i would have to keep track of the new added enums and add new switch statements to handle them.

@ Architect: i figured that much, any pointer on how to accomplish this would be great… i’m looking for ideas here…

thanks.

You need to do “reverse” to this one (reply by William):

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

His function returns string for enum value. You need to return enum value for string.

I agree with Architect’s solution for what you say you want to do. However, I have to question why you want to do this? The whole point of enums is to put a readable string name to an arbitrary fixed integer value. But, the values you are receiving are string values and not the integer values. So, why bother converting them to integer values if the source system doesn’t use the same integer values? Also, you say you don’t want to maintain a matching enum list on the client side. There’s no way around that unless what you really want is a dictionary where new values would be added automatically and persisted on an SD card. Again, you’ll have to write that custom dictionary. I think your best solution may be to just keep the string value.

Hello,
thank you guys for your replies…

@ Architect:
yep i knew that was one way to do it but as i explained before it would me keeping track to the enums and the Switch statement. basically adding an enum later mean remembering to add a case for it in the switch… which is prone to errors.

@ ianlee74:
the reason why i want it done that way is to make it easy for the dev and the end user. and here is how:

for DEV as you know using Enum forces them to not make mistakes, where they could pass in a non valid value which would happen if that was a string or an integer.(enums are great for design time).
and for the end user the same applies i would allow the user to send in a string instead of an integer because it is easier to read, maintain, and understand… where the code is more or less self explanatory, but if i used the integer value it would be hard to use the function at run-time without the proper documentation…

So when using Json, i wouldn’t have to explain to the end user the meaning of each argument or property since they would all be self explanatory… and when i say the end user that includes me few months later, when i try to use that same function and not remembering what each integer value means… LOL

maybe i’m going at this the wrong way…any other thoughts?

some sample code:(Don’t focus the meaning of the properties of class names they are just examples.


    /// <summary>
    /// Determines the type of a Blind.
    /// </summary>
    public enum BlindType
    {
        /// <summary>
        /// Indicates an unidentified value.
        /// </summary>
        None,
        /// <summary>
        /// Indicates some type one still to be determined.
        /// </summary>
        Type1,
        /// <summary>
        /// Indicates a type2.
        /// </summary>
        Type2,
        /// <summary>
        /// Indicates a type3.
        /// </summary>
        Type3,
    }

    public class Blind 
    {
        /// <summary>
        /// Initializes a new instance of the Blind class.
        /// </summary>
        public Blind()
        {
            Type = BlindType.None;
        }

         public string Name { get; set; }
         public BlindType Type { get; set; }
    }

//building  the object at design time (For DEVS):
var myBlind = new Blind { Name = "my BedRoom Blind" , Type= BlindType.Type2};

//building the object at run-time for end users through some interface (Json for example)

string myString = "{Name: 'Blind1', Type='Type2'}";
JsonToObject myNewBlind = JsonToObject (myString);

Debug.Print(myNewBlind.Name + " and " + JsonToObject.Type);

Would output:
Blind1 and Type2


Note: JsonToObject doesn’t exsist yet… and i’m not even sure if it would possible to create such function due to thelimitation of netMf… so if someone have gone that route maybe they can save me sometime by pointing me to the right the direction.
PS: i saw Wouter’s Json Code (Thank you Wouter) but i didn’t check it out, so i’m hoping it’ll have what i need. but i don’t think it supports Enums… or drills deep enough into the properties…

Cheers,
Jay.

Jay, even in my twisted skull I can’t imagine how you hope to achieve using enums without maintaining the enums list manually. C# can’t read your mind. Perhaps what you really need is a shared database table/service?

Hi,
@ ianlee74: i thought i was the only one with a twisted skull :smiley: my code is pretty clear on what it’s doing if you try in the full .net it’ll work as described. the issue is the missing enum.Parse function in netMF which I’m really hopping GHI would at least add to it’s extension of the assemblies.

if not i may have to find another way to do what i want…

thanks…

I understand BUT it still will not work w/o manually keeping your enum current which you say you don’t want to do. How about creating your own Parse() extension method for the enum? You’ll still have to maintain both your enum list and your Parse() lookup but at least it will feel like traditional .NET.

The idea with NetMF though is that the NetMF is open source, so people can contribute what they want. Perhaps it’d be better to wish for this over on the netmf codeplex site and see if anyone takes up the challenge? While I love the fact that GHI work so tirelessly to give us great fully featured add-ons to their firmware, this kind of “missing feature” should be a core feature in the framework, not necessarily something that someone in isolation adds. If GHI chose to assist in doing this for the core, that’s a decision they can make.

Hi,
@ ianlee74: i have written extensions already and i have plenty of them integrated in my Solution. trust me I’ve tried to create the Parse function on my Own but in doing so i ran into some more missing necessary feature from the core like GetAttribute and GetProperty, and so on… as you can see this is beyond my doing… at least that what i think…

@ Brett: i agree with you these should have been in the core from day one, not really sure how they stripped out and didn’t think people would use such features… my guess is they thought that the micro controllers are limited to being Program and compiled to run, without needing much of the Runtime features configuration and access…

anyway i’m up for the challenge but where do i start?

Thanks.

http://netmf.codeplex.com

netmf porting kit

Jay, the only limitation is the amount of memory and firmware available to these tiny devices. Only so much can fit on them. There’s not really any technical reasons that all of this couldn’t be implemented. The real question is are you willing to sacrifice available space for your programs on every device that has NETMF installed in order to have that feature. So, when implementing the core NETMF that is the question that has to be asked for every function implemented. Every core function added takes away space for your programs. Frankly, I’ve never needed this functionality. So, this leads me to think this is something that’s better added on a per program basis as opposed to being in the core.

There has been an open request to the core team for a long while to make it possible to have only the used parts of the core deployed to the device. Obviously this is not an easy request to fulfill but I believe someday that’s where we’ll end up.

that’s the whole idea of having assemblies…

if i need a function or two i can reference the assembly…so i still think that netMF team should consider adding these functions as assemblies for now and maybe incorporate them if ever needed into the core at later time… kind of like having a System.Utilities Assembly that would host all of these extra features… that one can reference or even take from and incorporate directly into their code…

@ Architect: I’m looking for more of a how to kind of think… where to get the full source code of the current .Parse function of the full .net and then port it to netmf preferably using C#.

thanks.

I am on a Mac at the moment, but have you heard of Reflector. This is a great tool. Load regular .Net assembly that has the method you are interested in and it will disassemble it into the language of your choice.

If you don’t have reflector I can check it later and post here.

ReSharper will pull the full source out of the .pdb files. Here’s the entire Enum class. Enjoy!


// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
using System.Reflection;
using System.Text; 
using System.Collections; 
using System.Globalization;
using System.Runtime.CompilerServices; 
using System.Runtime.InteropServices;
using System.Security;
using System.Runtime.Versioning;
using System.Diagnostics.Contracts; 

namespace System 
{ 
    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)] 
    public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
    {
        #region Private Static Data Members
        private static readonly char [] enumSeperatorCharArray = new char [] {','}; 
        private const String enumSeperator = ", ";
        private static Hashtable fieldInfoHash = Hashtable.Synchronized(new Hashtable()); 
        private const int maxHashElements = 100; // to trim the working set 
        #endregion
 
        #region Private Static Methods
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static HashEntry GetHashEntry(RuntimeType enumType)
        { 
            Contract.Requires(enumType != null);
            Contract.Ensures(Contract.Result<HashEntry>() != null); 
 
            HashEntry hashEntry = (HashEntry)fieldInfoHash[enumType];
 
            if (hashEntry == null)
            {
                // To reduce the workingset we clear the hashtable when a threshold number of elements are inserted.
                if (fieldInfoHash.Count > maxHashElements) 
                    fieldInfoHash.Clear();
 
                ulong[] values = null; 
                String[] names = null;
 
                GetEnumValues(enumType.GetTypeHandleInternal(),
                    JitHelpers.GetObjectHandleOnStack(ref values), JitHelpers.GetObjectHandleOnStack(ref names));

                hashEntry = new HashEntry(names, values); 
                fieldInfoHash[enumType] = hashEntry;
            } 
 
            return hashEntry;
        } 

        private static String InternalFormattedHexString(Object value)
        {
            TypeCode typeCode = Convert.GetTypeCode(value); 

            switch (typeCode) 
            { 
                case TypeCode.SByte :
                    { 
                        Byte result = (byte)(sbyte)value;

                        return result.ToString("X2", null);
                    } 

                case TypeCode.Byte : 
                    { 
                        Byte result = (byte)value;
 
                        return result.ToString("X2", null);
                    }

                case TypeCode.Int16 : 
                    {
                        UInt16 result = (UInt16)(Int16)value; 
 
                        return result.ToString("X4", null);
                    } 

                case TypeCode.UInt16 :
                    {
                        UInt16 result = (UInt16)value; 

                        return result.ToString("X4", null); 
                    } 

                case TypeCode.UInt32 : 
                    {
                        UInt32 result = (UInt32)value;

                        return result.ToString("X8", null); 
                    }
 
                case TypeCode.Int32 : 
                    {
                        UInt32 result = (UInt32)(int)value; 

                        return result.ToString("X8", null);
                    }
 
                case TypeCode.UInt64 :
                    { 
                        UInt64 result = (UInt64)value; 

                        return result.ToString("X16", null); 
                    }

                case TypeCode.Int64 :
                    { 
                        UInt64 result = (UInt64)(Int64)value;
 
                        return result.ToString("X16", null); 
                    }
 
                // All unsigned types will be directly cast
                default :
                    Contract.Assert(false, "Invalid Object type in Format");
                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); 
            }
        } 
 
        private static String InternalFormat(RuntimeType eT, Object value)
        { 
            Contract.Requires(eT != null);
            Contract.Requires(value != null);
            if (!eT.IsDefined(typeof(System.FlagsAttribute), false)) // Not marked with Flags attribute
            { 
                // Try to see if its one of the enum values, then we return a String back else the value
                String retval = GetName(eT, value); 
                if (retval == null) 
                    return value.ToString();
                else 
                    return retval;
            }
            else // These are flags OR'ed together (We treat everything as unsigned types)
            { 
                return InternalFlagsFormat(eT, value);
 
            } 
        }
 
        private static String InternalFlagsFormat(RuntimeType eT, Object value)
        {
            Contract.Requires(eT != null);
            Contract.Requires(value != null); 
            ulong result = ToUInt64(value);
            HashEntry hashEntry = GetHashEntry(eT); 
            // These values are sorted by value. Don't change this 
            String[] names = hashEntry.names;
            ulong[] values = hashEntry.values; 
            Contract.Assert(names.Length == values.Length);

            int index = values.Length - 1;
            StringBuilder retval = new StringBuilder(); 
            bool firstTime = true;
            ulong saveResult = result; 
 
            // We will not optimize this code further to keep it maintainable. There are some boundary checks that can be applied
            // to minimize the comparsions required. This code works the same for the best/worst case. In general the number of 
            // items in an enum are sufficiently small and not worth the optimization.
            while (index >= 0)
            {
                if ((index == 0) && (values[index] == 0)) 
                    break;
 
                if ((result & values[index]) == values[index]) 
                {
                    result -= values[index]; 
                    if (!firstTime)
                        retval.Insert(0, enumSeperator);

                    retval.Insert(0, names[index]); 
                    firstTime = false;
                } 
 
                index--;
            } 

            // We were unable to represent this number as a bitwise or of valid flags
            if (result != 0)
                return value.ToString(); 

            // For the case when we have zero 
            if (saveResult==0) 
            {
                if (values.Length > 0 && values[0] == 0) 
                    return names[0]; // Zero was one of the enum values.
                else
                    return "0";
            } 
            else
            return retval.ToString(); // Return the string representation 
        } 

        internal static ulong ToUInt64(Object value) 
        {
            // Helper function to silently convert the value to UInt64 from the other base types for enum without throwing an exception.
            // This is need since the Convert functions do overflow checks.
            TypeCode typeCode = Convert.GetTypeCode(value); 
            ulong result;
 
            switch(typeCode) 
            {
                case TypeCode.SByte: 
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                    result = (UInt64)Convert.ToInt64(value, CultureInfo.InvariantCulture); 
                    break;
 
                case TypeCode.Byte: 
                case TypeCode.UInt16:
                case TypeCode.UInt32: 
                case TypeCode.UInt64:
                    result = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
                    break;
 
                default:
                // All unsigned types will be directly cast 
                    Contract.Assert(false, "Invalid Object type in ToUInt64"); 
                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
            } 
            return result;
        }

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern int InternalCompareTo(Object o1, Object o2); 

        [System.Security.SecuritySafeCritical] 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern RuntimeType InternalGetUnderlyingType(RuntimeType enumType);
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        private static extern void GetEnumValues(RuntimeTypeHandle enumType, ObjectHandleOnStack values, ObjectHandleOnStack names); 

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern Object InternalBoxEnum(RuntimeType enumType, long value);
        #endregion 
 
        #region Public Static Methods
        private enum ParseFailureKind 
        {
            None                  = 0,
            Argument              = 1,
            ArgumentNull          = 2, 
            ArgumentWithParameter = 3,
            UnhandledException    = 4 
        } 

        // This will store the result of the parsing. 
        private struct EnumResult
        {
            internal object parsedEnum;
            internal bool canThrow; 
            internal ParseFailureKind m_failure;
            internal string m_failureMessageID; 
            internal string m_failureParameter; 
            internal object m_failureMessageFormatArgument;
            internal Exception m_innerException; 

            internal void Init(bool canMethodThrow)
            {
                parsedEnum = 0; 
                canThrow = canMethodThrow;
            } 
            internal void SetFailure(Exception unhandledException) 
            {
                m_failure = ParseFailureKind.UnhandledException; 
                m_innerException = unhandledException;
            }
            internal void SetFailure(ParseFailureKind failure, string failureParameter)
            { 
                m_failure = failure;
                m_failureParameter = failureParameter; 
                if (canThrow) 
                    throw GetEnumParseException();
            } 
            internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument)
            {
                m_failure = failure;
                m_failureMessageID = failureMessageID; 
                m_failureMessageFormatArgument = failureMessageFormatArgument;
                if (canThrow) 
                    throw GetEnumParseException(); 
            }
            internal Exception GetEnumParseException() 
            {
                switch (m_failure)
                {
                    case ParseFailureKind.Argument: 
                        return new ArgumentException(Environment.GetResourceString(m_failureMessageID));
 
                    case ParseFailureKind.ArgumentNull: 
                        return new ArgumentNullException(m_failureParameter);
 
                    case ParseFailureKind.ArgumentWithParameter:
                        return new ArgumentException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument));

                    case ParseFailureKind.UnhandledException: 
                        return m_innerException;
 
                    default: 
                        Contract.Assert(false, "Unknown EnumParseFailure: " + m_failure);
                        return new ArgumentException(Environment.GetResourceString("Arg_EnumValueNotFound")); 
                }
            }
        }
 
        [System.Security.SecuritySafeCritical]
        public static bool TryParse<TEnum>(String value, out TEnum result) where TEnum : struct 
        { 
            return TryParse(value, false, out result);
        } 

        [System.Security.SecuritySafeCritical]
        public static bool TryParse<TEnum>(String value, bool ignoreCase, out TEnum result) where TEnum : struct
        { 
            result = default(TEnum);
            EnumResult parseResult = new EnumResult(); 
            parseResult.Init(false); 
            bool retValue;
 
            if (retValue = TryParseEnum(typeof(TEnum), value, ignoreCase, ref parseResult))
                result = (TEnum)parseResult.parsedEnum;
            return retValue;
        } 

        [System.Runtime.InteropServices.ComVisible(true)] 
        public static Object Parse(Type enumType, String value) 
        {
            return Parse(enumType, value, false); 
        }

        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object Parse(Type enumType, String value, bool ignoreCase) 
        {
            EnumResult parseResult = new EnumResult(); 
            parseResult.Init(true); 
            if (TryParseEnum(enumType, value, ignoreCase, ref parseResult))
                return parseResult.parsedEnum; 
            else
                throw parseResult.GetEnumParseException();
        }
 
        [System.Security.SecuritySafeCritical]
        private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, ref EnumResult parseResult) 
        { 
            if (enumType == null)
                throw new ArgumentNullException("enumType"); 
            Contract.EndContractBlock();

            RuntimeType rtType = enumType as RuntimeType;
            if (rtType == null) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
 
            if (!enumType.IsEnum) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
 
            if (value == null) {
                parseResult.SetFailure(ParseFailureKind.ArgumentNull, "value");
                return false;
            } 

            value = value.Trim(); 
            if (value.Length == 0) { 
                parseResult.SetFailure(ParseFailureKind.Argument, "Arg_MustContainEnumInfo", null);
                return false; 
            }

            // We have 2 code paths here. One if they are values else if they are Strings.
            // values will have the first character as as number or a sign. 
            ulong result = 0;
 
            if (Char.IsDigit(value[0]) || value[0] == '-' || value[0] == '+') 
            {
                Type underlyingType = GetUnderlyingType(enumType); 
                Object temp;

                try
                { 
                    temp = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
                    parseResult.parsedEnum = ToObject(enumType, temp); 
                    return true; 
                }
                catch (FormatException) 
                { // We need to Parse this as a String instead. There are cases
                  // when you tlbimp enums that can have values of the form "3D".
                  // Don't fix this code.
                } 
                catch (Exception ex)
                { 
                    if (parseResult.canThrow) 
                        throw;
                    else 
                    {
                        parseResult.SetFailure(ex);
                        return false;
                    } 
                }
            } 
 
            String[] values = value.Split(enumSeperatorCharArray);
 
            // Find the field.Lets assume that these are always static classes because the class is
            //  an enum.
            HashEntry hashEntry = GetHashEntry(rtType);
            String[] names = hashEntry.names; 

            for (int i = 0; i < values.Length; i++) 
            { 
                values[i] = values[i].Trim(); // We need to remove whitespace characters
 
                bool success = false;

                for (int j = 0; j < names.Length; j++)
                { 
                    if (ignoreCase)
                    { 
                        if (String.Compare(names[j], values[i], StringComparison.OrdinalIgnoreCase) != 0) 
                            continue;
                    } 
                    else
                    {
                        if (!names[j].Equals(values[i]))
                            continue; 
                    }
 
                    ulong item = hashEntry.values[j]; 

                    result |= item; 
                    success = true;
                    break;
                }
 
                if (!success)
                { 
                    // Not found, throw an argument exception. 
                    parseResult.SetFailure(ParseFailureKind.ArgumentWithParameter, "Arg_EnumValueNotFound", value);
                    return false; 
                }
            }

            try 
            {
                parseResult.parsedEnum = ToObject(enumType, result); 
                return true; 
            }
            catch (Exception ex) 
            {
                if (parseResult.canThrow)
                    throw;
                else 
                {
                    parseResult.SetFailure(ex); 
                    return false; 
                }
            } 
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(true)] 
        public static Type GetUnderlyingType(Type enumType)
        { 
            if (enumType == null) 
                throw new ArgumentNullException("enumType");
            Contract.EndContractBlock(); 

            return enumType.GetEnumUnderlyingType();
        }
 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Array GetValues(Type enumType) 
        { 
            if (enumType == null)
                throw new ArgumentNullException("enumType"); 
            Contract.EndContractBlock();

            return enumType.GetEnumValues();
        } 

        internal static ulong[] InternalGetValues(RuntimeType enumType) 
        { 
            // Get all of the values
            return GetHashEntry(enumType).values; 
        }

        [System.Runtime.InteropServices.ComVisible(true)]
        public static String GetName(Type enumType, Object value) 
        {
            if (enumType == null) 
                throw new ArgumentNullException("enumType"); 
            Contract.EndContractBlock();
 
            return enumType.GetEnumName(value);
        }

        [System.Runtime.InteropServices.ComVisible(true)] 
        public static String[] GetNames(Type enumType)
        { 
            if (enumType == null) 
                throw new ArgumentNullException("enumType");
            Contract.EndContractBlock(); 

            return enumType.GetEnumNames();
        }
 
        internal static String[] InternalGetNames(RuntimeType enumType)
        { 
            return GetHashEntry(enumType).names; 
        }
 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, Object value)
        {
            if (value == null) 
                throw new ArgumentNullException("value");
            Contract.EndContractBlock(); 
 
            // Delegate rest of error checking to the other functions
            TypeCode typeCode = Convert.GetTypeCode(value); 

            switch (typeCode)
            {
                case TypeCode.Int32 : 
                    return ToObject(enumType, (int)value);
 
                case TypeCode.SByte : 
                    return ToObject(enumType, (sbyte)value);
 
                case TypeCode.Int16 :
                    return ToObject(enumType, (short)value);

                case TypeCode.Int64 : 
                    return ToObject(enumType, (long)value);
 
                case TypeCode.UInt32 : 
                    return ToObject(enumType, (uint)value);
 
                case TypeCode.Byte :
                    return ToObject(enumType, (byte)value);

                case TypeCode.UInt16 : 
                    return ToObject(enumType, (ushort)value);
 
                case TypeCode.UInt64 : 
                    return ToObject(enumType, (ulong)value);
 
                default :
                    // All unsigned types will be directly cast
                    throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
            } 
        }
 
        [Pure] 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static bool IsDefined(Type enumType, Object value) 
        {
            if (enumType == null)
                throw new ArgumentNullException("enumType");
            Contract.EndContractBlock(); 

            return enumType.IsEnumDefined(value); 
        } 

        [System.Runtime.InteropServices.ComVisible(true)] 
        public static String Format(Type enumType, Object value, String format)
        {
            if (enumType == null)
                throw new ArgumentNullException("enumType"); 

            if (!enumType.IsEnum) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); 

            if (value == null) 
                throw new ArgumentNullException("value");

            if (format == null)
                throw new ArgumentNullException("format"); 
            Contract.EndContractBlock();
 
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); 

            // Check if both of them are of the same type
            Type valueType = value.GetType();
 
            Type underlyingType = GetUnderlyingType(enumType);
 
            // If the value is an Enum then we need to extract the underlying value from it 
            if (valueType.IsEnum) {
                Type valueUnderlyingType = GetUnderlyingType(valueType); 

                if (!valueType.IsEquivalentTo(enumType))
                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), enumType.ToString()));
 
                valueType = valueUnderlyingType;
                value = ((Enum)value).GetValue(); 
            } 
            // The value must be of the same type as the Underlying type of the Enum
            else if (valueType != underlyingType) { 
                throw new ArgumentException(Environment.GetResourceString("Arg_EnumFormatUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
            }

            if( format.Length != 1) { 
                // all acceptable format string are of length 1
                throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification")); 
            } 

            char formatCh = format[0]; 

            if (formatCh == 'D' || formatCh == 'd') {
                return value.ToString();
            } 

            if (formatCh == 'X' || formatCh == 'x') { 
                // Retrieve the value from the field. 
                return InternalFormattedHexString(value);
            } 

            if (formatCh == 'G' || formatCh == 'g') {
                return InternalFormat(rtType, value);
            } 

            if (formatCh == 'F' || formatCh == 'f') { 
                return InternalFlagsFormat(rtType, value); 
            }
 
            throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
        }

        #endregion 

        #region Definitions 
        private class HashEntry 
        {
            // Each entry contains a list of sorted pair of enum field names and values, sorted by values 
            public HashEntry(String [] names, ulong [] values)
            {
                this.names = names;
                this.values = values; 
            }
 
            public String[] names; 
            public ulong [] values;
        } 
        #endregion

        #region Private Methods
        [System.Security.SecuritySafeCritical]  // auto-generated 
        internal Object GetValue()
        { 
            return InternalGetValue(); 
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private extern Object InternalGetValue(); 

        #endregion 
 
        #region Object Overrides
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        public extern override bool Equals(Object obj);
 
        public override int GetHashCode()
        { 
            return GetValue().GetHashCode(); 
        }
 
        public override String ToString()
        {
            // Returns the value in a human readable format.  For PASCAL style enums who's value maps directly the name of the field is returned.
            // For PASCAL style enums who's values do not map directly the decimal value of the field is returned. 
            // For BitFlags (indicated by the Flags custom attribute): If for each bit that is set in the value there is a corresponding constant
            //(a pure power of 2), then the  OR string (ie "Red | Yellow") is returned. Otherwise, if the value is zero or if you can't create a string that consists of 
            // pure powers of 2 OR-ed together, you return a hex value 
            return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
        } 
        #endregion

        #region IFormattable
        [Obsolete("The provider argument is not used. Please use ToString(String).")] 
        public String ToString(String format, IFormatProvider provider)
        { 
            return ToString(format); 
        }
        #endregion 

        #region IComparable
        [System.Security.SecuritySafeCritical]  // auto-generated
        public int CompareTo(Object target) 
        {
            const int retIncompatibleMethodTables = 2;  // indicates that the method tables did not match 
            const int retInvalidEnumType = 3; // indicates that the enum was of an unknown/unsupported unerlying type 

            if (this == null) 
                throw new NullReferenceException();
            Contract.EndContractBlock();

            int ret = InternalCompareTo(this, target); 

            if (ret < retIncompatibleMethodTables) 
            { 
                // -1, 0 and 1 are the normal return codes
                return ret; 
            }
            else if (ret == retIncompatibleMethodTables)
            {
                Type thisType = this.GetType(); 
                Type targetType = target.GetType();
 
                throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", 
                        targetType.ToString(), thisType.ToString()));
            } 
            else
            {
                // assert valid return code (3)
                Contract.Assert(ret == retInvalidEnumType, "Enum.InternalCompareTo return code was invalid"); 

                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); 
            } 
        }
        #endregion 

        #region Public Methods
        [System.Security.SecuritySafeCritical]  // auto-generated
        public String ToString(String format) { 
            if (format == null || format.Length == 0)
                format = "G"; 
 
            if (String.Compare(format, "G", StringComparison.OrdinalIgnoreCase) == 0)
                return ToString(); 

            if (String.Compare(format, "D", StringComparison.OrdinalIgnoreCase) == 0)
                return GetValue().ToString();
 
            if (String.Compare(format, "X", StringComparison.OrdinalIgnoreCase) == 0)
                return InternalFormattedHexString(GetValue()); 
 
            if (String.Compare(format, "F", StringComparison.OrdinalIgnoreCase) == 0)
                return InternalFlagsFormat((RuntimeType)GetType(), GetValue()); 

            throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
        }
 
        [Obsolete("The provider argument is not used. Please use ToString().")]
        public String ToString(IFormatProvider provider) 
        { 
            return ToString();
        } 

        public Boolean HasFlag(Enum flag) {
            if (!this.GetType().IsEquivalentTo(flag.GetType())) {
                throw new ArgumentException(Environment.GetResourceString("Argument_EnumTypeDoesNotMatch", flag.GetType(), this.GetType())); 
            }
 
            ulong uFlag = ToUInt64(flag.GetValue()); 
            ulong uThis = ToUInt64(GetValue());
            return ((uThis & uFlag) == uFlag); 
        }

        #endregion
 
        #region IConvertable
        public TypeCode GetTypeCode() 
        { 
            Type enumType = this.GetType();
            Type underlyingType = GetUnderlyingType(enumType); 

            if (underlyingType == typeof(Int32))
            {
                return TypeCode.Int32; 
            }
 
            if (underlyingType == typeof(sbyte)) 
            {
                return TypeCode.SByte; 
            }

            if (underlyingType == typeof(Int16))
            { 
                return TypeCode.Int16;
            } 
 
            if (underlyingType == typeof(Int64))
            { 
                return TypeCode.Int64;
            }

            if (underlyingType == typeof(UInt32)) 
            {
                return TypeCode.UInt32; 
            } 

            if (underlyingType == typeof(byte)) 
            {
                return TypeCode.Byte;
            }
 
            if (underlyingType == typeof(UInt16))
            { 
                return TypeCode.UInt16; 
            }
 
            if (underlyingType == typeof(UInt64))
            {
                return TypeCode.UInt64;
            } 

            Contract.Assert(false, "Unknown underlying type."); 
            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); 
        }
 
        /// <internalonly/>
        bool IConvertible.ToBoolean(IFormatProvider provider)
        {
            return Convert.ToBoolean(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/> 
        char IConvertible.ToChar(IFormatProvider provider)
        { 
            return Convert.ToChar(GetValue(), CultureInfo.CurrentCulture);
        }

        /// <internalonly/> 
        sbyte IConvertible.ToSByte(IFormatProvider provider)
        { 
            return Convert.ToSByte(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/>
        byte IConvertible.ToByte(IFormatProvider provider)
        {
            return Convert.ToByte(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/> 
        short IConvertible.ToInt16(IFormatProvider provider)
        { 
            return Convert.ToInt16(GetValue(), CultureInfo.CurrentCulture);
        }

        /// <internalonly/> 
        ushort IConvertible.ToUInt16(IFormatProvider provider)
        { 
            return Convert.ToUInt16(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/>
        int IConvertible.ToInt32(IFormatProvider provider)
        {
            return Convert.ToInt32(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/> 
        uint IConvertible.ToUInt32(IFormatProvider provider)
        { 
            return Convert.ToUInt32(GetValue(), CultureInfo.CurrentCulture);
        }

        /// <internalonly/> 
        long IConvertible.ToInt64(IFormatProvider provider)
        { 
            return Convert.ToInt64(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/>
        ulong IConvertible.ToUInt64(IFormatProvider provider)
        {
            return Convert.ToUInt64(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/> 
        float IConvertible.ToSingle(IFormatProvider provider)
        { 
            return Convert.ToSingle(GetValue(), CultureInfo.CurrentCulture);
        }

        /// <internalonly/> 
        double IConvertible.ToDouble(IFormatProvider provider)
        { 
            return Convert.ToDouble(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/>
        Decimal IConvertible.ToDecimal(IFormatProvider provider)
        {
            return Convert.ToDecimal(GetValue(), CultureInfo.CurrentCulture); 
        }
 
        /// <internalonly/> 
        DateTime IConvertible.ToDateTime(IFormatProvider provider)
        { 
            throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Enum", "DateTime"));
        }

        /// <internalonly/> 
        Object IConvertible.ToType(Type type, IFormatProvider provider)
        { 
            return Convert.DefaultToType((IConvertible)this, type, provider); 
        }
        #endregion 

        #region ToObject
        [System.Security.SecuritySafeCritical]  // auto-generated
        [CLSCompliant(false)] 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, sbyte value) 
        { 
            if (enumType == null)
                throw new ArgumentNullException("enumType"); 
            if (!enumType.IsEnum)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            Contract.EndContractBlock();
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); 
            return InternalBoxEnum(rtType, value); 
        }
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, short value)
        {
            if (enumType == null) 
                throw new ArgumentNullException("enumType");
            if (!enumType.IsEnum) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); 
            Contract.EndContractBlock();
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
            return InternalBoxEnum(rtType, value);
        } 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(true)] 
        public static Object ToObject(Type enumType, int value) 
        {
            if (enumType == null) 
                throw new ArgumentNullException("enumType");
            if (!enumType.IsEnum)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            Contract.EndContractBlock(); 
            RuntimeType rtType = enumType as RuntimeType;
            if (rtType == null) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); 
            return InternalBoxEnum(rtType, value);
        } 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, byte value)
        { 
            if (enumType == null)
                throw new ArgumentNullException("enumType"); 
            if (!enumType.IsEnum) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            Contract.EndContractBlock(); 
            RuntimeType rtType = enumType as RuntimeType;
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
            return InternalBoxEnum(rtType, value); 
        }
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [CLSCompliant(false)] 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, ushort value) 
        {
            if (enumType == null)
                throw new ArgumentNullException("enumType");
            if (!enumType.IsEnum) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            Contract.EndContractBlock(); 
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); 
            return InternalBoxEnum(rtType, value);
        }
        [System.Security.SecuritySafeCritical]  // auto-generated
        [CLSCompliant(false)] 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, uint value) 
        { 
            if (enumType == null)
                throw new ArgumentNullException("enumType"); 
            if (!enumType.IsEnum)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            Contract.EndContractBlock();
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); 
            return InternalBoxEnum(rtType, value); 
        }
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [System.Runtime.InteropServices.ComVisible(true)]
        public static Object ToObject(Type enumType, long value)
        {
            if (enumType == null) 
                throw new ArgumentNullException("enumType");
            if (!enumType.IsEnum) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); 
            Contract.EndContractBlock();
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
            return InternalBoxEnum(rtType, value);
        } 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [CLSCompliant(false)] 
        [System.Runtime.InteropServices.ComVisible(true)] 
        public static Object ToObject(Type enumType, ulong value)
        { 
            if (enumType == null)
                throw new ArgumentNullException("enumType");
            if (!enumType.IsEnum)
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); 
            Contract.EndContractBlock();
            RuntimeType rtType = enumType as RuntimeType; 
            if (rtType == null) 
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
            return InternalBoxEnum(rtType, unchecked((long)value)); 
        }
        #endregion
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

Jay, I understand your frustration, and agree with the points you are making. I am curious though how the string that represents the enum value gets created on the user’s application? When I write web applications using full .Net for customers I use lots of enums. When I want a user to choose from a list of enumerated values, I usually fill a dropdown with the enum item names and their values, and let the user choose one. They choose an item by name, but I send back the value of the item to the application as an integer which I then convert to an enumerated type using Enum.Parse.

Also, in these lines of code you use a method called “JsonToObject” to create a “JsonToObject” object, but I dont’ see how you convert that into an object of type “Blind”?


string myString = "{Name: 'Blind1', Type='Type2'}";
JsonToObject myNewBlind = JsonToObject (myString);

@ ianlee74:
thanks for pointing that out, i already have Resharper and use the decompiler from time to time…
@ jasdev: please take a look at Wouter’s code: http://code.tinyclr.com/project/343/json-generation-library/

that should get you started in the right direction…
as for my library it isn’t finished yet…

thanks.
Jay.