1

执行上下文嵌套事件

嗨,我想了解更多关于 an 的执行上下文IObserver<T>以及与“嵌套事件”相关的信息。

基本上,当我将它与 linq-to-IEnumerable 进行比较时,我会构建一个表达式树,并且当我调用诸如ToList()……之类的东西时会被执行。例如

Var singleCustomer = from customer in customers
            Where customer.ID == 2
            Select customer.FirstOrDefault();

这只是一个被执行的表达式(我假设当我执行时FirstOrDefault)......这如何与IObservable世界一起工作?我认为它的工作原理几乎相同......我会很高兴对此有一些意见......</p>

这与我真正的问题有关,因为我有一些 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>()但就像我说的我对内在价值更感兴趣......

我想出了这个……</p>

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 风格吗?有什么改进建议吗?

4

1 回答 1

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

于 2012-03-23T09:02:04.690 回答