执行上下文嵌套事件
嗨,我想了解更多关于IObserver<T>
的执行上下文以及与"嵌套事件"相关的信息。
基本上,当我将其与linq和IEnumerable进行比较时,我会建立一个表达式树,当我调用ToList()
等时,我就会被执行。例如
Var singleCustomer = from customer in customers
Where customer.ID == 2
Select customer.FirstOrDefault();
这只是一个被执行的表达式(我假设当我执行FirstOrDefault
时)…这在IObservable
世界中是如何工作的?我想它会几乎一样工作…我会很高兴有一些关于这个…的意见
这与我的真实问题有关,因为我有一些Event,它是某种事件容器。
event EventHandler<ContainerEventArgs> ContainerReady;
ContainerEventArgs
会包含一个坐标数组……我必须在那里做一个运算,才能得到我要找的特定坐标(中心坐标)。中心坐标是我真正喜欢观察的东西。当这一切发生变化时,我想得到通知,。。
在没有Rx的标准.Net方式中,我会做这样的事情来获取CenterCoordinate的坐标更改事件。
ContainerReady += (s,e) => {
var container = e.GetContainer();
var coordinate = new point[e.CoordinatesArrayLength]();
e.CopyCoordinatesToArray(container);
if(coordinates != null){
var particularCoordinate = from coordinate in coordinates.where(… center coordinates…).FirstOrDefault();
if(particularCoordinate != null){
if(CenterCoordinateUpdated != null)
{
CenterCoordinateUpdated(this, new CenterCoordinateUpdatedEventArgs(){
CenterPosition = particularCoordinates;
}
}
}
}
假设我有这样的第二个事件:
event EventHandler<CenterCoordinatesUpdatedEventArgs> CenterCoordinateUpdated;
好的,长话短说…现在我该如何处理RX?到目前为止,我所拥有的是:
public IObservable<Container> GetContainers(){
var containerSource = Observerable.FromeEventPattern< ContainerEventArgs>(this,”ContainerReady”);
var container = from evt in containerSource.Where(x=>x.EventArgs.GetContainer != null)
select evt.GetContainers();
return container;
}
所以这返回了一个IObservable<Container>()
,但正如我所说,我对内部值更感兴趣…
我想出了这个…
public IObservable<CenterCoordinates> GetContainers(){
var containerSource = Observerable.FromeEventPattern< ContainerEventArgs>(this,”ContainerReady”);
var container = from evt in containerSource.Where(x=>x.EventArgs.GetContainer != null)
select evt.GetContainers();
var centerCoordinate = from cc in container
select GetCenterCoordinates(cc); //Get CenterCoordinates does the Array copy stuff
return centerCoordinate.SkipWhile(x=>x … center condition… );
}
我的SkipWhile
和GetCenterCoordinates
方法有意义吗?还是我订阅了任何事件(与我使用IEnumerable的介绍有关),因为我需要先打开坐标?…什么时候执行Observable表达式树?或者我不需要关注(表演)吗?是否有更好的方法使用主题或发布其他事件来处理此问题?这是RX风格吗?有什么改进建议吗?
您的需求非常适合Rx,您只需要多一点练习:-)
让我试着帮你。我希望我能满足你的要求。
您的查询可以用这种简单的方式编写:
public IObservable<CenterCoordinates> GetContainers()
{
var containerSource = Observerable.FromeEventPattern<ContainerEventArgs>(this, "ContainerReady");
var query = containerSource
.Select(ev => ev.EventArgs.GetContainer) // project event args into containers
.Where(container => container != null) // filter null containers
.SelectMany(container => GetCenterCoordinates(container)) // expand the stream of containers into a stream of center coordinates
.Where(cc => .. center condition ..); // filter only center that match a certain condition
return query;
}
如果你喜欢查询语法,你也可以这样写:
public IObservable<CenterCoordinates> GetContainers()
{
var containerSource = Observerable.FromeEventPattern<ContainerEventArgs>(this, "ContainerReady");
var query = from ev in containerSource
let container = ev.EventArgs.GetContainer
where container != null
from cc in GetCenterCoordinates(container)
where cc .. center condition ..
select cc;
return query;
}
熟悉SelectMany
:它是LINQ中最重要的运算符之一(包括LINQ到对象和Rx)。
还有一个小的更正:我们在这里讨论的LINQ查询没有被编译器翻译成表达式树。它们被翻译成一系列扩展方法,就像我在第一个例子中展示的那样。表达式树用于更复杂的场景(例如LINQ到SQL)。