将对象强制转换为具有“泛型值”的KeyValuePair

本文关键字:泛型 泛型值 KeyValuePair 对象 转换 | 更新日期: 2023-09-27 18:14:28

我有一个ComboBox,里面有两种不同类型的混合项。类型为

KeyValuePair<Int32, FontFamily>

KeyValuePair<Int32, String>

现在有些情况下,我只对所选项的Key感兴趣,它总是Int32。

访问所选项的Key最简单的方法是什么?我在想

Int32 key = ((KeyValuepair<Int32, object/T/var/IdontCare>)combobox.SelectedItem).Key;

但这行不通。

所以我只有

    Int32 key;
    if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, FontFamily)))
    {
        key = ((KeyValuePair<Int32, FontFamily)combobox.SelectedItem).Key;
    }
    else if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, String)))
    {
        key = ((KeyValuePair<Int32, String)combobox.SelectedItem).Key;
    }

的工作,但我想知道是否有一个更优雅的方式?

将对象强制转换为具有“泛型值”的KeyValuePair

转换到dynamic(穷人的倒影)可以做到这一点

var key = (int) ((dynamic) comboxbox.SelectedItem).Key);

您当然不需要使用GetType()。您可以使用:

int key;
var item = combobox.SelectedItem;
if (item is KeyValuePair<int, FontFamily>)
{
    key = ((KeyValuePair<int, FontFamily>) item).Key;
}
else if (item is KeyValuePair<int, string>)
{
    key = ((KeyValuePair<int, string>) item).Key;
}

我认为没有更好的方法不使用反射或动态类型,假设你不能改变所选项目的类型为你自己的等效KeyValuePair与一些非泛型基类型或接口。

我猜它是在WPF中绑定的,在这种情况下,我建议不要使用KeyValuePair<TKey,TValue>,而是使用自己的VM类。例如

class MyComboItem
{
    private String _stringValue;
    private FontFamiliy _fontFamilyValue;
    public Int32 Key {get;set;}
    public object Value => (_fontFamilyValue!=null)?_fontFamilyValue:_stringValue;
}

或者你可以有一个像

这样的接口
interface IMyComboItem
{
    Int32 Key {get;}
    object Value {get;}
}

并实现两个VM类来实现它存储正确的值类型。有合适的构造函数等等。使用泛型无法实现您想要实现的强制类型转换,而且您的解决方案不够优雅。

您可以像这样创建自己的类层次结构

public interface IComboBoxItem
{
    public int Key { get; }
}
public class ComboBoxItem<T> : IComboBoxItem
{
    public T Value { get; set; }
    public int Key { get; set; }
}

,你的cast看起来像这样:

key = ((IComboBoxItem)combobox.SelectedItem).Key;

基于Rich的回答,我成功地使用了Dynamic。我知道要绑定的字典类型(实际上可以使用字典本身,因为它仍然在我的表单中被引用),但是我想创建一个通过displayname进行搜索的方法。这将最终检查绑定源是否也是一个数据表,但目前,这对于<字符串(?>)字典。

private void SetComboBoxSelection(ComboBox cmb, string ItemText)
        {
            if (cmb.DisplayMember.ToLower() == "key" && cmb.ValueMember.ToLower() == "value")
            {
                foreach (dynamic item in cmb.Items)
                    if (item.Key == ItemText)
                        cmb.SelectedItem = item.Value;
            }
        }