using System; using System.Collections.Generic; using System.Globalization; using System.Linq; namespace NTwain.Data { /// /// Utility on converting (possibly bad) integer values to enum values. /// public static class ValueConverter { public static IList CastToEnum(this IEnumerable list) where T : struct,IConvertible { return list.CastToEnum(true); } public static IList CastToEnum(this IEnumerable list, bool tryUpperWord) where T : struct,IConvertible { return list.Select(o => o.ConvertToEnum(tryUpperWord)).ToList(); } public static T ConvertToEnum(this object value) where T : struct,IConvertible { return ConvertToEnum(value, true); } public static T ConvertToEnum(this object value, bool tryUpperWord) where T : struct,IConvertible { var returnType = typeof(T); // standard int values if (returnType.IsEnum) { if (tryUpperWord) { // small routine to work with bad sources that may put // 16bit value in the upper word instead of lower word (as per the twain spec). var rawType = Enum.GetUnderlyingType(returnType); if (typeof(ushort).IsAssignableFrom(rawType)) { var intVal = Convert.ToUInt32(value, CultureInfo.InvariantCulture); var enumVal = GetLowerWord(intVal); if (!Enum.IsDefined(returnType, enumVal)) { return (T)Enum.ToObject(returnType, GetUpperWord(intVal)); } } } // this may work better? return (T)Enum.ToObject(returnType, value); //// cast to underlying type first then to the enum //return (T)Convert.ChangeType(value, rawType); } else if (typeof(IConvertible).IsAssignableFrom(returnType)) { // for regular integers and whatnot return (T)Convert.ChangeType(value, returnType, CultureInfo.InvariantCulture); } // return as-is from cap. if caller made a mistake then there should be exceptions return (T)value; } static ushort GetLowerWord(uint value) { return (ushort)(value & 0xffff); } static uint GetUpperWord(uint value) { return (ushort)(value >> 16); } /// /// Tries to convert to a value to if possible. /// /// The value. /// public static TWFix32 ConvertToFix32(this object value) { if (value is TWFix32) { return (TWFix32)value; } return (TWFix32)Convert.ToSingle(value, CultureInfo.InvariantCulture); } } }