如何在表达式树中订阅对象的事件? [英] How do I subscribe to an event of an object inside an expression tree?
问题描述
说我有一个这样的构造函数
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屋!