如何在表达式树中订阅对象的事件?

时间:2009-12-20 20:12:40

标签: .net events expression-trees

抱歉,我想不出一个更好的头衔。这是一个只能在一起理解的两部分问题。

说我有这样的构造函数

public Fact(INotifyPropertyChanged observable, Func<bool> predicate)
{
    this.predicate = predicate;
    observable.PropertyChanged += (sender, args) =>
                     PropertyChanged(this, new PropertyChangedEventArgs("Value"));

}

这就是它的使用方式

new Fact(Model.AllowEditing, () => Model.AllowEditing);

其中AllowEditing是一种INotifyPropertyChanged

我想将构造函数重构为

public Fact(Expression<Func<bool>> expression)

所以它可以像这样调用

new Fact(() => Model.AllowEditing);

问题是如何解析该表达式以从表达式树中获取“可观察”然后订阅它的事件?

上面的代码不是我的,它来自Ayende最近的一个示例,如果有人想看看Fact类的使用情况,这里就像完整的源代码一样http://github.com/ayende/Effectus < / p>

1 个答案:

答案 0 :(得分:1)

基本上,在这种情况下您需要的对象存储在expression.Body.Expression中。您将需要编译并执行表达式树来获取它。此外,您可能需要检查类型是否真正实现了您的界面以及谓词是否是您真正想要的。

这是一个非常粗略的代码:

public Fact(Expression<Func<bool>> predicate)
{        
    this.predicate = predicate;
    MemberExpression body = predicate.Body as MemberExpression;

    // Check that you get a valid lambda expression, 
    // like object.Member, not something like !object.Member
    if (body == null) 
         throw new ArgumentException("'" + predicate + "': is not a valid expression for this method");
    var type = body.Expression.Type;

    // Check if type implements INotifyPropertyChanged using reflection  
    // ...

    INotifyPropertyChanged observable = 
    Expression.Lambda<Func<INotifyPropertyChanged>>(body.Expression).Compile()();
    //...
}