代码之家  ›  专栏  ›  技术社区  ›  Qwertie

输入字典?

  •  5
  • Qwertie  · 技术社区  · 15 年前

    有人听说过“类型字典”使用类型作为键并支持继承吗?

    在我的应用程序中,我希望有一个从类型到函数的字典,大致如下:

    Dictionary<Type, Func<object, object>> Transformers;
    

    其思想是,它将用于根据对象的类型以某种方式转换对象:

    // Transform an object 'obj'
    object result = Transformers[obj.GetType()](obj)
    

    普通词典的缺点是类型必须完全匹配。因此,如果我为IList编写了一个transformer<t>,那么将它放入transformer s字典是没有用的,因为没有对象具有类型IList<t>(只有t[]、list<t>,等等)换句话说,如果obj是list<t>,则在一本普通的字典。

    假设没有类型字典,如果不太难的话,我可能会考虑写一本。有什么想法可以实现吗?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Community CDub    8 年前

    你应该能用一本字典 custom comparer 使用的 Type.IsAssignableFrom 比较钥匙。

    更新: 正如qwertie指出的,这不起作用,因为您不能基于类型、其接口和祖先类实现可重复的哈希代码计算。 His answer 通过重复对类型、接口和祖先类进行哈希表查找,直到找到匹配项,提供了可能的解决方案。

    该解决方案的唯一问题是,当存在多个匹配项时,您没有任何方法指定要采用的匹配项。如果你需要这种灵活性和控制力,我建议你考虑 chain-of-responsibility 设计模式。每个转换器可能是链中的一个链接,它负责确定是否可以将其应用于对象。如果没有,则将请求传递到下一个链接。链中变压器的顺序决定了优先级。你失去了散列表的速度,但是由于多次查找,你还是失去了一些速度。

        2
  •  1
  •   Qwertie    15 年前

    我突然意识到词典设置器的语义与普通词典没有区别,因此一种方法是使用具有专门查找功能的标准词典:

    public class TypeDictionary<TValue> : Dictionary<Type, TValue>
    {
        public new TValue this[Type key]
        {
            get {
                TValue value;
                if (TryGetValue(key, out value))
                    return value;
                throw new KeyNotFoundException("Not found: " + key.Name);
            }
        }
        public new bool TryGetValue(Type key, out TValue value)
        {
            if (base.TryGetValue(key, out value))
                return true;
    
            Type[] interfaces = key.GetInterfaces();
            for (int i = 0; i < interfaces.Length; i++)
                if (base.TryGetValue(interfaces[i], out value))
                    return true;
    
            Type @base = key.BaseType;
            if (@base != null && TryGetValue(@base, out value))
                return true;
    
            return false;
        }
    }
    

    请注意,如果类B派生自类A以及接口IA和IB,并且有一个值分配给这些类型中的每一个,那么它是不明确的:应该返回A、IA或IB的值吗?上面的实现选择它找到的第一个接口,并且只有在没有找到接口的情况下,它才会寻找基类。

    我不知道这本词典的性能有多好。如果getinterfaces()或basetype属性很慢,则会使查找性能很差(无论何时您请求的确切类型不在字典中)。