Execution Context nested Events
Hi,
I would like to know a little bit more about the execution context of an IObserver<T> and related to “nested events”.
Basically when I compare it to linq-to-IEnumerable, I build up an expression tree and I gets executed when I call something like ToList()… etc.
For example
Var singleCustomer = from customer in customers
Where customer.ID == 2
Select customer.FirstOrDefault();
This is only an expression which gets executed (I assume when I execute FirstOrDefault)…
How does this work with the IObservable world? I assume it would work almost the same… I would be great to have some input on this…
This relates to my real question because I have some Event which is some sort of an event container.
event EventHandler<ContainerEventArgs> ContainerReady;
and the ContainerEventArgs would contain an Array of Coordinates… And I have to do an operation there to get out the particular coordinates (centercoordinate) I am looking for.
The centercoordinates would the thing I really like to observe on. WhenEver this changes I would like to get Notified,..
In the standard .Net way without Rx I would do something like this to get my Coordinate Change Event for the 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;
}
}
}
}
Assuming I have some second event like this:
event EventHandler<CenterCoordinatesUpdatedEventArgs> CenterCoordinateUpdated;
Ok long story … now How should I handle this with RX? What I have so far is this:
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;
}
So this returns an IObservable<Container>() but like I said I am more interested in the inner values …
I came up with this…
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… );
}
Does my SkipWhile and GetCenterCoordinates methods make sense? Or do I subscribe anyway to any event (related to my intro with IEnumerable) because I need to unpack the coordinates first?…When is the Observable Expression-Tree executed? Or do I not need to pay attention on that(performance)?
Is there a better way to handle this using Subjects or publish other events? Is this RX-Style? Any improvement suggestions?
Your requirement are really suited for Rx, you just need a little more practice 🙂
Let me try and help. I hope I got your requirements right.
Your query could be written in this simple way:
if you prefer the query syntax, you can also write it like this:
Get familiar with
SelectMany: it is one of the most important operators in LINQ (both LINQ to objects, and Rx).And a small correction: the LINQ queries that we’re talking about here are not translated by the compiler into expression trees. They are translated into a chain of extension methods, like I’ve shown in my first example. Expression trees are used in more complex scenarios (e.g. LINQ to SQL).