是否可以创建一个通用的Int-to-Enum转换器?
我想能说
如果int
值等于(int)MyEnum.Value
其解析为True
我知道我可以创建一个返回(MyEnum)intValue
的Converter
,但是我必须为我在DataTriggers中使用的每个Enum类型创建一个转换器。
有没有一种通用的方法来创建一个能够给我这种function的转换器?
可以以可重用的方式在枚举值及其底层整数类型之间创建转换器 – 也就是说,您不需要为每个枚举类型定义新的转换器。 为Convert
和Convert
提供了足够的信息。
public sealed class BidirectionalEnumAndNumberConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null) return null; if (targetType.IsEnum) { // convert int to enum return Enum.ToObject(targetType, value); } if (value.GetType().IsEnum) { // convert enum to int return System.Convert.ChangeType( value, Enum.GetUnderlyingType(value.GetType())); } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { // perform the same conversion in both directions return Convert(value, targetType, parameter, culture); } }
调用时,此转换器仅基于value
和targetType
值在int / enum值之间翻转值的类型。 没有硬编码的枚举类型。
我想我想通了
我只需要设置我的ConverterParameter
而不是Value
等于我正在寻找的Enum,并评估为True / False
变流器
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (parameter == null || value == null) return false; if (parameter.GetType().IsEnum && value is int) { return (int)parameter == (int)value; } return false; }
你也可以反过来使用自定义标记扩展将枚举转换为int的int。
例
EnumToIntExtension
public class EnumToIntExtension : MarkupExtension { public object EnumValue { get; set; } public EnumToIntExtension(object enumValue) { this.EnumValue = enumValue; } public override object ProvideValue(IServiceProvider provider) { if (EnumValue != null && EnumValue is Enum) { return System.Convert.ToInt32(EnumValue); } return -1; } }
我们过去也想过几次这样做,所以我们构建了几个扩展方法(在int,long等)来帮助我们。 所有这些的核心都是在一个静态通用的TryAsEnum方法中实现的:
/// /// Helper method to try to convert a value to an enumeration value. /// /// If is not convertable to , an exception will be thrown /// as documented by Convert.ChangeType. /// /// The value to convert to the enumeration type. /// The enumeration type value. /// true if value was successfully converted; false otherwise. /// Thrown if is not an enum type. (Because we can't specify a generic constraint that T is an Enum.) public static bool TryAsEnum( TValue value, out TEnum outEnum ) where TEnum : struct { var enumType = typeof( TEnum ); if ( !enumType.IsEnum ) { throw new InvalidOperationException( string.Format( "{0} is not an enum type.", enumType.Name ) ); } var valueAsUnderlyingType = Convert.ChangeType( value, Enum.GetUnderlyingType( enumType ) ); if ( Enum.IsDefined( enumType, valueAsUnderlyingType ) ) { outEnum = (TEnum) Enum.ToObject( enumType, valueAsUnderlyingType ); return true; } // IsDefined returns false if the value is multiple composed flags, so detect and handle that case if( enumType.GetCustomAttributes( typeof( FlagsAttribute ), inherit: true ).Any() ) { // Flags attribute set on the enum. Get the enum value. var enumValue = (TEnum)Enum.ToObject( enumType, valueAsUnderlyingType ); // If a value outside the actual enum range is set, then ToString will result in a numeric representation (rather than a string one). // So if a number CANNOT be parsed from the ToString result, we know that only defined values have been set. decimal parseResult; if( !decimal.TryParse( enumValue.ToString(), out parseResult ) ) { outEnum = enumValue; return true; } } outEnum = default( TEnum ); return false; }
此实现处理具有任何基础类型的枚举,以及使用[Flags]属性定义的枚举。
您可以对int值执行ToString(),然后将其传递给静态Enum.Parse或Enum.TryParse方法,该方法采用您关心的枚举类型并返回适当的值。
这不是一个完美的解决方案,因为它不适用于表示多个枚举值的二进制ORing的整数