具有嵌套事件的IObservable上的执行上下文

时间:2012-03-19 20:06:16

标签: c# system.reactive reactive-programming

执行上下文嵌套事件

您好, 我想更多地了解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… );
}

我的SkipWhileGetCenterCoordinates方法是否有意义?或者我是否订阅任何事件(与我的IEnumerable简介相关)因为我需要首先解压缩坐标?... Observable Expression-Tree何时执行?或者我不需要关注(性能)? 有没有更好的方法来处理使用主题或发布其他事件?这是RX风格吗?有任何改进建议吗?

1 个答案:

答案 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)。