2010-12-13 103 views
3

如何在字典中使用某种类型的表达式>作为关键字?使用表达式<Func<object>>作为字典中的关键字

我刚开始玩表达式实例,不知道我想做什么是可能的。

看起来2个相同的表达式与我尝试时不相同我可以使用表达式作为键将条目放入字典中,但当我询问字典是否包含键时,它将返回false,除非我使用非常相同的表情实例。

TypeToTest test = new TypeToTest(); 
Expression<Func<object>> expression =()=>test.PropertyA; 
IDictionary<Expression<Func<object>>,bool> dictionary = new Dictionary<Expression<Func<object>>, bool>(); 
dictionary[expression] = true; 
Assert.That (dictionary.ContainsKey(expression), Is.True); 
Assert.That (dictionary.ContainsKey(()=>test.PropertyA), Is.True); 

上面的最后一行失败,当我希望它成功。

意图是有能力定义一组适用于对象的属性或方法的规则,以便我可以确定(例如)某个属性是可编辑的还是具有字典中特定键的值可以删除。我不希望在对象上有一个标志确定它是否可编辑(因为可编辑性对于不同的属性可能不同),另一个标志确定它是否可删除,而是另一个负责维护关联规则的类与对象一起使用,以便在未来扩展对象时,可以添加更多规则来描述对象组成部分的可编辑性/可访问性/可删除性/。如果这是有道理的。

有类似的帖子here,但这似乎是基于属性名称的关键,因为我希望能够键入方法和参数,所以我可以支持确定持有对象的可编辑性在基于密钥的字典中。

会这样的事情是可能的还是它在天空中馅饼?

回答

4

这是比较不同参考时的预期行为,其中该类型不会覆盖Equals或实施IEquatable<T>。你可能写一个自定义比较器(可能只是比较ToString())并将其传递到字典 - 但IMO和Expression不是一个很好的选择的关键。

以下是不一定是通过ToString();在使用自己的判断:

class Program { 
    static void Main() { 
     TypeToTest test = new TypeToTest(); 
     Expression<Func<object>> expression =() => test.PropertyA; 
     IDictionary<Expression<Func<object>>, bool> dictionary = 
      new Dictionary<Expression<Func<object>>, bool>(
       new ToStringComparer<Expression<Func<object>>>()); 
     dictionary[expression] = true; 

     bool x = dictionary.ContainsKey(expression), // true 
      y = dictionary.ContainsKey(() => test.PropertyA); // true 
    } 
} 
class ToStringComparer<T> : IEqualityComparer<T> where T : class { 
    public bool Equals(T x, T y) { 
     if ((x == null && y == null) || ReferenceEquals(x,y)) return true; 
     if (x == null || y == null) return false; 
     return x.ToString() == y.ToString(); 
    } 
    public int GetHashCode(T obj) { 
     return obj == null ? 0 : obj.ToString().GetHashCode(); 
    } 
} 
+0

你为什么认为它不是一个很好的选择?它似乎允许每个属性/方法单独控制其可访问性,如果类型被扩展(可以使用另一个接口) – 2010-12-13 11:43:09

+0

@Sam - 因为没有明确定义的相等性检查,所以可以轻松地扩充该类型。例如;是'x => x.A'与'y => y.A'有相同的表达式吗?如果表达式捕获一个捕获变量包装的对象实例会怎么样? – 2010-12-13 11:44:10

+0

很好的解决方案。 – IamStalker 2014-04-22 12:09:00

2

Expression类型的子类不重写EqualsGetHashCode方法,使他们也很难使用字典键。您的字典使用引用相等性,并且()=>test.PropertyA的两次出现产生两个不同的表达式树对象。

您可以编写自己的IEqualityComparer<Expression>实现,并将其传递到字典构造函数中。在你的比较器中,你可以编写EqualsGetHashCode方法来处理每个Expression类并比较它们的属性。

+0

'Expression'覆盖'GetHashCode',因此'IEqualityComparer '实现可能能够委托实现(只检查相同的实例是否给出相同的哈希码)。 – Richard 2010-12-13 14:51:14

相关问题