执行上下文嵌套事件
您好,
我想更多地了解IObserver<T>
的执行上下文并与“嵌套事件”相关。
基本上当我将它与linq-to-IEnumerable进行比较时,我构建了一个表达式树,当我调用类似ToList()
之类的东西时我会执行...等等。
例如
Var singleCustomer = from customer in customers
Where customer.ID == 2
Select customer.FirstOrDefault();
这只是一个被执行的表达式(我假设当我执行FirstOrDefault
时)...
这对IObservable
世界有何影响?我认为它的工作方式几乎相同......我很高兴能对此有所了解......
这与我真正的问题有关,因为我有一些事件是某种事件容器。
event EventHandler<ContainerEventArgs> ContainerReady;
并且ContainerEventArgs
将包含一个坐标数组......我必须在那里进行操作以获得我正在寻找的特定坐标(centercoordinate)。
中心坐标是我真正想要观察的事情。当这个改变时我想得到通知,..
在没有Rx的标准.Net方式中,我会做这样的事情来获得CenterCoordinate的Coordinate Change事件。
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 Expression-Tree何时执行?或者我不需要关注(性能)?
有没有更好的方法来处理使用主题或发布其他事件?这是RX风格吗?有任何改进建议吗?
答案 0 :(得分:1)
您的要求非常适合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 to objects和Rx)。
一个小的修正:我们在这里讨论的LINQ查询不会被编译器翻译成表达式树。它们被翻译成一系列扩展方法,就像我在第一个例子中所示。表达式树用于更复杂的场景(例如LINQ to SQL)。