I need some explain on Rx behavior - c#

When I use Reactive Extensions (Rx) with linq filter what happen under the hood?
Is this,
var move = Observable.FromEventPattern<MouseEventArgs>(frm, "MouseMove");
IObservable<System.Drawing.Point> points = from evt in move
select evt.EventArgs.Location;
var overfirstbisector = from pos in points
where pos.X == pos.Y
select pos;
var movesub = overfirstbisector.Subscribe(pos => Console.WriteLine("mouse at " + pos));
more efficient from this?
private void MouseMove(object sender, EventArgs args)
{
if (args.Location.X == args.LocationY)
Console.WriteLine("mouse at " + args.Location);
}
I dont talk about the filtering logic itself but about the events behavior of the methods.
In Rx do the event raised exactly the same way of the regular event but with warapper or there is somthing special under the hood?

In this case, there's no algorithmic performance benefit for using the Rx query over the typical event handler - in fact, your Rx query may actually be marginally slower than the typical event handler. "Under the hood" the Rx query is basically doing the same thing as the typical event handler, but in a cleaner way.

The Rx query is not more efficient than the directly subscribing the events. Under the hood, the Rx query is still subscribing to the events and adding a bit of logic (e.g. for the schedulers), so I would say you are trading a bit of performance for increased readability, flexibility (since you can quickly change and adapt the query) and testability (since the Rx query can be much more easily unit-tested).

There is nothing "special" about Rx. Rx is just a library, not a language feature. If you wanted to, you could have built Rx yourself in a normal old C# project, it just happened that the smart people at Microsoft thought of it first. The code is open source now so you can just download it and see how it all works (admittedly it got a lot more complex in v2)
In your example, the Rx code will need to do the following:
Reflectively look for an event called "MouseMove" on the frm object
Create an observable sequence (IObservable<MouseEventArgs>) from the event
Ensure the safe semantics of the implicit IObservable contract e.g. that values are sequential, the subscriptions are thread safe etc..
Do the condition check
Subscribe to the sequence (safely)
Print to the console when a value is pushed.
In contrast, the non-rx code does the following:
Recieves a virtual call from a base class
does the condition check
Prints the value to the console.
So no reflection & no safety checks, but the same result. In practice the performance will be very fast for both so you are unlikely to see any performance difference.
With regards to Unit testing, I think any argument for or against is nonsense. We are talking about a MouseMove event, how are you going to unit test that? Putting all that Rx in your code base doesn't appear to pay for itself in my opinion (slower, more code, another framework for a dev to understand, etc...)

Related

Which C# pattern has better performance to avoid duplicated event handlers?

There are basically two patterns in avoiding duplicated registering of event handlers:
(According to this discussion: C# pattern to prevent an event handler hooked twice)
Using System.Linq namespace, and check if the event handler is registered by calling GetInvocationList().Contains(MyEventHandlerMethod);
Do the unregistering before registering, like this:
MyEvent -= MyEventHandlerMethod;
MyEvent += MyEventHandlerMethod;
My question is, performance-wise, which one is better, or is there a significant difference between them in performance?
I don't think this matters a lot, both in assumed performance gain and actual difference.
Both GetInvocationList and -= walk the internal array _invocationList. (See source)
The LINQ extension method Contains will take more time since it needs the entire array to be walked and converted, returned and then checked by Contains itself. The Contains has the advantage it doesn't need to add the event handler if it exists which will mean some performance gain.
won't work for external callers, and is not very efficient anyway
should be fine (note that it creates 2 delegate instances each time, though), however also consider
in most scenarios, it should be easy to know whether you are already subscribed; if you can't know, then that suggests an architectural problem
The typical usage would be "subscribe {some usage} [unsubscribe]" where the unsubscribe may not be necessary, depending on the relative lifetimes of the event publisher and subscriber; if you actually have a re-entrant scenario, then "subscribe if not already subscribed" is itself problematic, because when unsubscribing later, you don't know if you're preventing an outer iteration receiving the event.
According the documentation, invocation list is being stored as array or something similar to it, and the order of the event handlers is being stored too. May be there are inner structure to maintain fast search for a particular method there.
So in the worst case operation of the GetInvocationList().Contains(MyEventHandlerMethod); is O(1) (as we simply got the reference for the array) + O(n) for searching the method, even if there is no optimization for it. I seriously doubt that this is true, and I think that there is some optimizing code, and it is O(log_n).
Second approach has additional operation of adding which is, I think, O(1), as we adding the event handler to the end.
So, to see the difference between such actions, you need a lot of the event handlers.
But! If you use the second approach, as I said, you'll add the event handler to the end of the queue, which can be wrong in some cases. So use the first one, and has no doubt in it.
MyEvent -= MyEventHandlerMethodfirst need to find the registered event handler in the invocation list in order to remove it.
So GetInvocationList().Contains is better, but it's truely insignificant.
But, notice that you can't access event EventHandler foo's invocation list....

What is the NO_PERF flag in reactive extensions source code doing

In the ReactiveExtensions source code there are huge swathes of codes switching between different implementations such as
https://github.com/Reactive-Extensions/Rx.NET/blob/master/Rx.NET/Source/System.Reactive.Linq/Reactive/Linq/QueryLanguage.StandardSequenceOperators.cs
and a snippet
#if !NO_PERF
return new Distinct<TSource, TSource>(source, x => x, EqualityComparer<TSource>.Default);
#else
return Distinct_(source, x => x, EqualityComparer<TSource>.Default);
#endif
what is the intention of this flag NO_PERF and what is the difference in behaviour between the library compiled with it and without it.
As a member of the Rx team, I can answer this:
The answer goes back to our changes from Rx 1.1 to Rx 2.0. We wanted the ability to keep the old style of using AnonymouseObservable around just in case, but for most of the time, you want the performance enhanced version.
There are big differences in both performance, and in some cases more eager disposal. You can find out more information about our changes here.
It's used to switch in/out logic that favours safety over performance. For example, in most of the operator implementations an AnonymousObservable is created to wrap OnXXX invocations and catch exceptions in observers.
When !NO_PERF is true this wrapper is not created - this shortens the call chain for queries and results in less objects, less GC pressure and faster code - but it's less safe as it assumes well-behaved observers.
This code has lots of examples.
I don't know, but I can see it being used inside other MS code that is a client of Rx, understands the consequences and is prepared to take on the responsibility of creating well-behaved clients.

Binding from child

hi i wanna pass the textboxquantidadehoras.Text;datahorado.SelectedDate; correto.Desenvolvedor(from childwindow) to a grid in the main page called datagridhorastotais but i can't set the itemsource to "teste" form child window... any ideas? here is the code of the childwindow
public partial class ChildWindow2 : ChildWindow, INotifyPropertyChanged
{
public class Horas : INotifyPropertyChanged
{
private string quantidadehoras;
private DateTime? datahora;
private string desenvolvedor;
public string Quantidadehoras
{
get
{
return quantidadehoras;
}
set
{
quantidadehoras = value;
NotifyPropertyChanged("Quantidadehoras");
}
}
public DateTime? Datahora
{
get
{
return datahora;
}
set
{
datahora = value;
NotifyPropertyChanged("DataHora");
}
}
public string Desenvolvedor
{
get
{
return desenvolvedor;
}
set
{
desenvolvedor = value;
NotifyPropertyChanged("Desenvolvedor");
}
}
#region
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public class Horas2 : ObservableCollection<Horas>
{
public Horas2()
{
}
}
}
#endregion
public ChildWindow2()
{
InitializeComponent();
}
public class quadrodehorarios : ObservableCollection<ChildWindow2>, INotifyPropertyChanged
{
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
Horas2 teste= new Horas2();
Horas correto = new Horas();
correto.Quantidadehoras = textboxquantidadehoras.Text;
correto.Datahora = datahorado.SelectedDate;
correto.Desenvolvedor =textboxDesenvolvedor.Text;
this.DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void textboxqtdhoras_TextChanged(object sender, TextChangedEventArgs e)
{
}
}
}
I’m working up my chapter on the “Event Aggregator” pattern for my book this evening and I’m starting by collecting my thoughts on the subject. If you feel like you have to comment and give me free advice for this chapter, then I guess you should do that (please). I’ve written about the pattern before here and here. I’m also referencing some other patterns that I haven’t written much about yet. Ward Bell and John Papa have both blogged on these patterns. I’ll blog about my StoryTeller implementation tomorrow night.
In case you’re new to the pattern, the Event Aggregator object will:
Channel events from multiple objects into a single object to simplify registration for clients.
In essence, it’s a specialized form of the GoF Mediator pattern. It’s a “hub” object in your application that you can use to do decoupled “publish/subscribe” messaging between different parts of your application. I’ve used the pattern with WinForms apps, WPF with StoryTeller, and even JavaScript in web pages (going to be very important as we implement a dashboard pattern for our web app at work).
Here’s my braindump on the pattern:
Registration. Somebody has to be responsible for registering the listeners with the event aggregator hub.
You could have the listeners themselves do the registration by taking a dependency on the event aggregator as is idiomatic with Prism. This is great because it makes it obvious when looking at a class whether or not it is registered as a listener. I’m not a fan of this approach because I think it’s awkward and adds repetitive code to each listener – and repetitive code should be stamped out wherever it pops up.
You could use another object like a “Screen Activator” (more on this pattern later) to do the registration of ViewModels/Presenters, screens, or non-UI elements as listeners. This has the advantage of removing the responsibility of bootstrapping away from the class (ViewModel/Presenter/service) that does the real work.
This is really just 2a, but you could use a custom “Registry” class to make the explicit subscriber subscriptions in one place. I like
Use conventional registration with an IoC tool to automatically add objects to the event aggregator as appropriate. I use a marker interface plus a StructureMap “interceptor” to do this in StoryTeller. This is the “easiest” mechanically, but adds some overhead to understanding how the pieces connect. But, and there’s a big but, conventions are black magic rather than explicit code.
Discoverability/Traceability. An event aggregator is a form of indirection, and indirection almost always makes a system a little harder to understand. At some point you definitely need to understand what objects are publishing and which are receiving events. Strong typed events are a boon here because it’s relatively easy to use advanced IDE features like R#’s “Find Usages” to quickly determine publishers and subscribers to a particular type of event. The event aggregator analogue in CAB depended on string keys and made troubleshooting harder. Event aggregator implementations in JavaScript and other dynamic languages will have the same issue.
Diagnostics. For those of us using static typed languages, you might want to add a diagnostic report that can be generated on demand that can scan the codebase and identify publishers and subscribers based on a dependency on the event aggregator. Using marker interfaces or common super types for message classes can make the diagnostics much easier.
Event Filtering. Simply put, not every subscriber cares about every instance of a type of event. For example, StoryTeller has several widgets that need to respond to every single test event (queued, executing, finished), but the individual test screens only respond to events involving their one particular test. In this case you need to worry about how events are filtered. The responsibility for the filtering can be in:
The listener itself. The listener knows what it cares about, so let it decide whether or not to continue processing the event.
Filter within the EventAggregator itself. You can either register the listeners with a subject like this: EventAggregator.Register(this, myTest), but this is assuming a specialized event aggregator that “knows” about the subject. Another way is to make the registration with a Predicate or Func to filter within the event aggregator. I’m still experimenting here inside StoryTeller with this pattern a little bit.
I’m thinking about having either an IoC interceptor or a Screen Activator do the filtered event registration. Again, the point is to move the grunt work of setting up the screen out of the ViewModel/Presenter to keep the ViewModel/Presenter relatively clean
Thread Marshalling. It’s very handy to just let the event aggregator take care of marshalling callbacks to the screen back to the UI thread. The Prism Event Aggregator gives you fine grained control over whether or not the marshalling should take place. Maximum control might be nice when every bit of performance matters, but then again, it makes you error prone in a part of the code that is hard to test.
Queuing. At this point I let the StoryTeller EventAggregator just process things synchronously, but running the event publishing on a background thread or queuing events up may be necessary to conserve resources.
Open/Closed Principal. Using the Event Aggregator makes it much, much easier to add new features to your system without modifying existing code as you would have to if you were dependent upon direct communication without an event aggregator. This is an important issue for teams doing incremental delivery or cases where multiple teams are working on the same system in parallel.
Garbage Collection: Your event aggregator has to keep a reference to all the subscribers. This can present you with some serious memory leak issues as screens are closed, but not garbage collected if the event aggregator is keeping a reference. You can beat the issue by using WeakReferences internally inside your event aggregator. The other option is to explicitly un-register listeners. The WeakReference strategy may be more reliable, but has its own issues. Explicit un-registration isn’t that bad if you are using a “Screen Conductor” to manage the screen activation lifecycle. Much more on that later…
Event Latching. Two issues here:
It might be valuable to ignore events at times. I’m specifically thinking about the case of a screen on a tab that is not active/displayed. Let’s say that this screen receives an event about financial market data being updated. The act of updating the hidden screen’s display turns out to be very expensive in terms of resources. You might want to quietly ignore or “latch” events when a screen is deactivated and hidden. That of course adds some complexity to make the hidden screen “know” to update itself when it is activated again. I think this is where the “Screen Activator” and “Screen Conductor” patterns come into play. If there’s a standard workflow that happens whenever a user activates a tab, then the “screen activator” should get an Activate() call.
In some specialized cases you may want the Event Aggregator to “latch” itself while in the midst of responding to an event. This is especially important when a widget responding to an event publishes other events. Think about “change” events getting published during the act of binding a screen to new data. In this case the event aggregator should ignore new events until the first is completely finished.
Event Ordering. It might be important that events be completely processed in the order that they arrive to the event aggregator. For example, Chad & I had an issue last year with a subscriber receiving an event, then publishing other events that were processed before the original event reached all of its subscribers. There might be a code smell in there somewhere, but event ordering may be something you need to consider.
One size does not fit all: It can often be advantageous to have multiple event aggregators within one application. I often find it useful to use an event aggregator that is scoped within a single complex “Composite View” when a single screen is very complicated within its own right.
Instrumentation. The EventAggregator is effectively a message bus and has all the same advantages as a message bus. Sending all events through the event aggregator gives you a great centralized place to put instrumentation code. Less repetitive code == fewer mistakes and better productivity.
What about the Prism EventAggregator?
Many people first come into contact with the Event Aggregator pattern through the implementation in Prism. For my regular readers you may be shocked (shocked I say!) to know that I don’t particularly care for the way they implemented the pattern in Prism. I think the Prism implementation is clumsy and awkward to use. I despise that idiom of first getting the event aggregator, then retrieving an “Event” object that I’ll then listen to. Same thing with publishing. I think it’s awkward that I have two steps (get event, then publish) instead of just saying “IEventAggregator.Send().” All of that is unnecessary noise code, and the “get event, then listen/publish” adds a little bit of overhead to every single unit test that I write that involves either listening to or sending events (more mock object setup, and that would add up more than the extra production code). No, that’s not a huge deal, but noise code adds up, and every bit of ceremony/noise code I can remove due to infrastructure will make me more productive and the code easier to deal with by making it easier to read.
All I want is to go:
IEventAggregator.Send( the message ). Nothing else.
The listeners should have little or preferably NO/ZILCH/NADA coupling to the event aggregator.
I think Prism is far better than CAB, but it’s still headed for some of the same problems that CAB had. The complexity and awkwardness of the EventAggregator in Prism is directly caused by trying to make the EventAggregator generalized to every possible scenario that you can think of. You will be able to create a better implementation of EventAggregator for your application by tailoring something simpler for only the things you need. At a minimum, you could at least put an application specific wrapper around Prism’s generalized API’s to make them easier to consume. I think you could stand to sacrifice some of the flexibility of the Prism EventAggregator and end up with a simpler to consume alternative.
Don’t take this as a specific criticism of Prism itself, because the real issue is that generalized application frameworks are an automatic compromise. The single most important reason that Prism is better than CAB is that you could easily, and I do mean easily, roll your own Event Aggregator and replace the one in Prism while still using the rest of Prism. Hooray for “Composition over Inheritance.” You couldn’t do that with CAB.
Wiki:
God willing and the river don’t rise, I will have a public Wiki up for the Presentation Patterns book by the end of the weekend. On advice from multiple people, I’ll be writing most of the first draft on the public Wiki. I’ll announce it as soon as it exists.
If I understand what you are trying to do... You could use a Mediator pattern such as the Event Aggregator to communicate an event (the data selection) from the childwindow to the parent window. Here is a StackOverflow question that covers the Event Aggregator.

C#: is calling an event handler explicitly really "a good thing to do"?

This question is related to C#, but may be applicable to other languages as well. I have a reservation against using code such as the following:
using System.Windows.Forms;
class MyForm : Form
{
private Timer myTimer;
private Button myButton;
public MyForm()
{
// Initialize the components, etc.
myTimer.Tick += new EventHandler( myTimer_Tick );
myButton.Click += new EventHandler( myButton_Click );
myTimer.Start();
}
private void myTimer_Tick( object sender, EventArgs eventArgs )
{
myTimer.Stop();
// also, I see a lot of usage of
// Timer.Enabled = true/false instead of -^
myButton_Click( this, ea /* or event EventArgs.Empty, or null */ );
return;
}
private void myButton_Click( object sender, EventArgs eventArgs )
{
// do a lot of stuff, with lots of logic that doesn't even use the
// state of the eventArgs
return;
}
}
Am I alone, in that the above style is a pet peeve of mine? Are there others who enjoy the clarity of separating event handling from the workload of functions, or even separating out complex routines into separate functions?
Is there even an accepted style? I feel like any expressiveness and flexibility that event handling in C# has can be lost with styles like this. I feel like if you have a method that means "a button has been clicked", then it should only be called when a button is clicked.
To those who write like this, I would say: if you insist on having an EventHandler method to handle your timer tick, and your button click, then call it something other than button_Click -- perhaps "handleUserEvent( object sender, EventArgs eventArgs )".
Really, though, the question is, are there any style guidelines that are widely used which either support or discourage usage such as the above?
This is definitely not a "personal preference". There is a clear, well-understood approach of how to write code that is well-structured, maintainable, reusable, and understandable. Each method in your code should encapsulate a single piece of reusable functionality. The structure of your code should be:
void ButtonClickEventHandler(...)
{
UserData userData = //determine user data from event data
DoUserThing(userData);
}
void DoUserThing(UserData userData)
{
//do stuff
}
void SomeOtherMethod()
{
UserData userData = //get userdata from some other source
DoUserThing(userData);
}
(This is a very loose example. In a proper application everything should be separated into different classes by concern.)
I agree with Rex M's answer, but I'd take it one step further. If you are using the MVC pattern (or something similar), the view would delegate the button click to the controller. The controllers methods can of course be called from elsewhere in your class - say, from your timer callback.
So, back to your original code:
using System.Windows.Forms;
class MyForm : Form
{
private Timer myTimer;
private Button myButton;
private MyController myController;
public MyForm()
{
// ...
// Initialize the components, etc.
// ...
myTimer.Tick += new EventHandler( myTimer_Tick );
myButton.Click += new EventHandler( myButton_Click );
myTimer.Start();
}
private void myTimer_Tick( object sender, EventArgs eventArgs )
{
myTimer.Stop();
myController.SomeMethod()
}
private void myButton_Click( object sender, EventArgs eventArgs )
{
// All the stuff done here will likely be moved
// into MyController.SomeMethod()
myController.SomeMethod();
}
}
One advantage of using MVC is the decoupling of the controller from the view. The controller can now be used across multiple view types easily and exiting GUIs are easier to maintain as they contain very little application logic.
EDIT: Added in response to comments from the OP
The fundamental design principals of software engineering talk about coupling and cohesion. Importantly we strive to minimise coupling between components while maximising cohesion as this leads to a more modular and maintainable system. Patterns like MVC and principals like the Open/Closed Principal build on these fundamentals, providing more tangible patterns of implemenation for the developer to follow.
So, anyone who writes code as seen in the original post has not understood the fundamentals of software design and needs to develop their skills considerably. The OP should be commended for identifying this "code smell" and trying to understand why it's not quite right.
Some relevant references:
http://en.wikipedia.org/wiki/Coupling_(computer_science)
http://en.wikipedia.org/wiki/Cohesion_(computer_science)
http://en.wikipedia.org/wiki/Loose_coupling
http://en.wikipedia.org/wiki/Model–view–controller
http://en.wikipedia.org/wiki/Design_patterns
http://en.wikipedia.org/wiki/Open/closed_principle
http://en.wikipedia.org/wiki/Design_Patterns_(book)
myButton.PerformClick() is probably slightly nicer, if you don't need to pass eventargs. Sometimes you just want to simulate a click.
But yes, I would agree that it's nicer to move the real code into another function. I prefer my event handlers to be very simple - just connect the UI to the logic, which is elsewhere.
Then you can rearrange and redesign your UI without worrying so much about where the logic is.
This code increase the chance of problems if another coder works on the myButton_Click method.
What if I came in to adjust the implementation of the myButton.Click handler? I might assume that the sender object is a Button, and try to cast:
Button b = (Button)sender;
I have no knowledge without reading the rest of the class implementation that I'm not always receiving a Button as the sender.
So my point is: -1 for maintainability, because of breaking the assumptions of what objects will be passed as myButton_Click parameters.
The short answer is that why would you simulate a button click by calling the handler directly? If you want to wire both methods up to the same event, you would just wire it up. Event handlers are multicast delegates, which means you can add more than one of them. Wiring up an event more than once is totally acceptable.
myTimer.Tick += myTimer_Tick;
myTimer.Tick += myButton_Click;
myButton.Click += myButton_Click;
Whether or not this is a WTF is an engineering call that we can't make from a short code snippet. However, based on your comments, it smells like a WTF. Forms or any UI should never handle business logic. They need to be business-logic-aware to some degree (as in validation) but they don't encapsulate / enforce the logic themselves.
Going further, following some simple practices as basic refactorings and using a layered (n-tier) approach to software will take you a long way, and you will realise along the way that the code you presented smells bad.
Eventually you'll come across some high-level patterns like MVC (model-view-controller) and MVP (model-view-presenter) which go a step beyond the simple layering. If you follow them you get a good separation of concerns.
I agree with the accepted answer, but jumping right into 'Use MVC', here's some code that doesn't illustrate MVC, without explaining why is a little cargo-cult for me.
The special things about events in C# (and the .Net framework in general is the delegate, which is the C/C++ equivalent of a function pointer. the method attached to the event itself is not special in any way and should be callable from anywhere.
Update:
perhaps I should have been more verbose, but I thought my use of "should" instead of "can" or "may" would be enough. It is my assertion that event handlers should be called when the functionality they implement is needed, instead of having them become wrappers to methods that "do the work" the less method calls you have in the stack the better you will be, specially with the performance implications of .Net's exception handling.
I know it's a long time since this was asked but I'm going to differ and say no. As long as (1) it works and (2) it's clear what it does. I've heard all the standard arguments about design principles and such but think sometimes people go overboard and forget about the basics of design in not making things overly complicated. I see this in people forcing OOB where procedural design is really more suited as well.
One response is to move the code elsewhere and instead call that function but the problem with arbitrarily moving code is it creates unnecessary duplication making it more complex and less readable which is the opposite of good design. Following the approach of having one function do one thing people end up having to call a bunch of functions from multiple places only really succeeding in creating more opportunities for errors and additional overhead.
I believe this is what's responsible for all of the bloat we're seeing in buggy programs. I'm rather from the school of reusing and grouping as much as what makes sense and if that includes calling a function directly instead of indirectly where it makes sense and does the same thing then that can actually improve readability and decrease complexity.

C# Best practice: Centralised event controller or not

I have an app which consists of several different assemblies, one of which holds the various interfaces which the classes obey, and by which the classes communicate across assembly boundaries. There are several classes firing events, and several which are interested in these events.
My question is as follows: is it good practice to implement a central EventConsolidator of some kind? This would be highly coupled, as it would need to know every class (or at least interface) throwing an event, and every consumer of an event would need to have a reference to EventConsolidator in order to subscribe.
Currently I have the situation where class A knows class B (but not C), class B knows class C, etc. Then if C fires an event B needs to pick it up and fire its own event in order for A to respond. These kinds of chains can get quite long, and it may be that B is only interested in the event in order to pass it along. I don't want A to know about C though, as that would break encapsulation.
What is good practice in this situation? Centralise the events, or grin and bear it and define events in each intermediate class? Or what are the criteria by which to make the decision? Thanks!
Edit: Here is another question asking essentially the same thing.
You could put the event itself in an interface, so that A didn't need to know about C directly, but only that it has the relevant event. However, perhaps you mean that the instance of A doesn't have sight of an instance of C...
I would try to steer clear of a centralised event system. It's likely to make testing harder, and introduced tight coupling as you said.
One pattern which is worth knowing about is making event proxying simple. If B only exposes an event to proxy it to C, you can do:
public event FooHandler Foo
{
add
{
c.Foo += value;
}
remove
{
c.Foo -= value;
}
}
That way it's proxying the subscription/unsubscription rather than the act of raising the event. This has an impact on GC eligibility, of course - which may be beneficial or not, depending on the situation. Worth thinking about though.
What you could try is using the event brokering of either NInject or the Unity Application Block.
This allows you to, for example:
[Publish("foo://happened")]
public event EventHandler<FooArgs> FooHappened;
[Subscribe("foo://happened")]
public void Foo_Happened(object sender, FooArgs args)
{ }
If both objects are created through the container the events will be hooked up automatically.
I'd probably try to massage the domain so that each class can directly depend on the appropriate event source. What I mean is asking the question why don't A know about C? Is there perhaps a D waiting to emerge?
As an alternative approach you could consider an event broker architecture. It means observers don't know directly about the source. Here's an interesting video.
This would be highly coupled, as it would need to know every class
I think you answered your own question if you consider that coupling is bad! Passing events through a chain of potential handlers is a fairly common pattern in many environments; It may not be the most efficient approach, but it avoids the complexity that your suggested approach would involve.
Another approach you could take is to use a message dispatcher. This involves using a common message format (or at least a common message header format) to represent events, and then placing those messages into a queue. A dispatcher then picks up each of those events in turn (or based on some prioritisation), and routes them directly to the required handler. Each handler must be registered with the dispatcher at startup.
A message in this case could simply be a class with a few specific fields at the start. The specific message could simply be a derivative, or you could pass your message-specific data as an 'object' parameter along with the message header.
You can check out the EventBroker object in the M$ patterns and practises lib if you want centralised events.
Personally I think its better to think about your architecture instead and even though we use the EventBroker here, none of our new code uses it and we're hoping to phase it out one sunny day.
we have our own event broker implementation (open source)
Tutorial at: http://sourceforge.net/apps/mediawiki/bbvcommon/index.php?title=Event_Broker
And a performance analysis at: www.planetgeek.ch/2009/07/12/event-broker-performance/
Advantages compared to CAB:
- better logging
- extension support
- better error handling
- extendable handlers (UI, Background Thread, ...)
and some more I cannot recall right now.
Cheers,
Urs

Categories