繁体   English   中英

使用泛型类型类将对象转换为特定的Enum

[英]Object to specific Enum conversion with generic type class

我在几个组合框的选择中显示了几个枚举。 我正在使用转换器从缓存的属性字典中获取显示名称。 当我将对象明确地转换为特定的Enum进入转换器时,没有任何问题(我使用参数对象和一个开关来确定要显式转换的Enum),但是,我想使此控件更通用且可用于任何控件我在视图绑定到基于枚举的属性。

这是我在转换器上尝试过的方法:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value != null)
    {
        Type t = Nullable.GetUnderlyingType(value.GetType()) ?? value.GetType();
        var item = System.Convert.ChangeType(value, t);
        return item.GetEnumDisplayName();
    }
    else
        return DependencyProperty.UnsetValue;
}

这是缓存字典对象:

public static class EnumDisplayCache<T> //where T : struct, IComparable, IFormattable, IConvertible
{
    private static Dictionary<T, string> _cache;

    static EnumDisplayCache()
    {
        _cache = new Dictionary<T, string>();
        Type type = typeof(T);
        foreach (T e in Enum.GetValues(type).Cast<T>())
            _cache.Add(e, e.GetDisplayName());
    }

    public static string GetDisplayName(T value)
    {
        return _cache[value];
    }
}

未显示“ GetEnumDisplayName”的扩展方法,但仅将T传递给缓存字典。

这是例外:

提供的类型必须是枚举。

我该如何将该对象转换为其原始枚举? 当我逐步调试器中的代码时,该类型在转换器中似乎是正确的。

更新了扩展方法:

internal static string GetDisplayName<T>(this T enumValue) //where T : struct, IComparable, IFormattable, IConvertible
{
        return enumValue.GetType()?
                        .GetMember(enumValue.ToString())?
                        .First()?
                        .GetCustomAttribute<DisplayAttribute>()?
                        .GetName() ?? enumValue.ToString();
}

public static string GetEnumDisplayName<T>(this T value) //where T : struct, IComparable, IFormattable, IConvertible
{
    return EnumDisplayCache<T>.GetDisplayName(value);
}

使用XAML和ViewModel更新:

<DataTemplate>
    <ComboBox ItemsSource="{Binding PossibleDimensions}"
                           SelectedItem="{Binding Dimensionality, Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Converter={StaticResource enumToDisplayConverter}, 
                                                         ConverterParameter='dimensionality'}" />
            </DataTemplate>
         </ComboBox.ItemTemplate>
      </ComboBox>
</DataTemplate>

ViewModel:

public List<Dimensionality> PossibleDimensions { get { return _possibleDimensions; } }
private static List<Dimensionality> _possibleDimensions;
public Dimensionality Dimensionality
{
    get { return (DataContext as Analog).Dimensionality; }
    set
    {
        if (value != (DataContext as Analog).Dimensionality)
        {
            (DataContext as Analog).Dimensionality = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Dimensionality"));
        }
    }
}

这不起作用,因为您在转换器中调用的System.Convert.ChangeType方法返回一个object而不是Dimensionality 因此,您实际上是在调用object.GetEnumDisplayName而不是Dimensionality.GetEnumDisplayName

如果取消注释类型约束,您将看到更清晰的代码,因为代码甚至无法编译。

如果您摆脱了无法使用的缓存,那么您的扩展方法将可以工作:

public static class EnumExtensions
{
    internal static string GetDisplayName<T>(this T enumValue) //where T : struct, IComparable, IFormattable, IConvertible
    {
        return enumValue.GetType()?
                        .GetMember(enumValue.ToString())?
                        .First()?
                        .GetCustomAttribute<DisplayAttribute>()?
                        .GetName() ?? enumValue.ToString();
    }

    public static string GetEnumDisplayName<T>(this T value) //where T : struct, IComparable, IFormattable, IConvertible
    {
        return GetDisplayName(value);
    }
}

但是您将必须调用GetType()方法来获取当前枚举值的运行时类型 就是这样,或者将System.Convert.ChangeType的结果强制转换为特定的枚举类型。 枚举类型没有任何“泛型”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM