如何在表达式树中订阅对象的事件? [英] How do I subscribe to an event of an object inside an expression tree?

查看:160
本文介绍了如何在表达式树中订阅对象的事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,我想不出更好的头衔。这是一个两部分的问题,只有一起有意义。



说我有一个这样的构造函数

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

}

这是如何使用

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

其中AllowEditing是INotifyPropertyChanged的一种类型



我想将构造函数重构为

  public Fact(Expression< Func< bool>>表达式)

所以可以这样调用

事实(()=> Model.AllowEditing); 

问题是如何解析该表达式,从表达式树中获取observable,然后订阅它的事件?



上面的代码不是我的,它来自Ayende的一个最近的例子,如果有人想看看如何事实类正在使用 http://github.com/ayende/Effectus

解决方案

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



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

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

//检查你是否获得了一个有效的lambda表达式,
// like object.Member,而不是像... object.Member
if(body == null)
throw new ArgumentException('+谓词+':不是此方法的有效表达式);
var type = body.Expression.Type;

//检查类型是否使用反射来实现INotifyPropertyChanged
// ...

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


Sorry I couldn't think of a better title. This is a two part question that only make sense together.

Say I have a constructor like this

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

}

and this is how it's used

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

where AllowEditing is a type of INotifyPropertyChanged

I would like to refactor the constructor into

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

So it can be call like this

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

The question is how to parse that expression to get "observable" out of the expression tree then subscribe to its event?

The code above is not mine, it come from an example recent example from Ayende, here is the like to the full source code if anyone want to take a look of how the Fact class is being used http://github.com/ayende/Effectus

解决方案

Basically, the object you need in this case is stored in expression.Body.Expression. You will need to compile and execute an expression tree to get it. Also, you will probably need to check whether the type really implements your interface and whether the predicate is what your really are looking for.

Here is a very rough code:

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()();
    //...
}

这篇关于如何在表达式树中订阅对象的事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆