Event Aggregation...What exactly is going on? - wpf

I have often times wondered about it but now that I have encountered a piece of logic that incorporates it, I thought I should go ahead and get some help on deciphering the fundamentals. The problem is as follows, I am looking at a WPF application that is utilizing the Composite Application Library. Within the source of the application I came across the following line of code in the Presentation of a view. For the sake of convinience I will call it Presentation A:
private void OnSomethingChanged(SomeArgumentType arguement)
{
UnityImplementation.EventAggregator.GetEvent<EventA>().Publish(null);
}
When I saw the method Publish in the above given method, my gut told me there must be a Subscribe somewhere and in another class, I will call it Presentation B there was the following:
UnityImplementation.EventAggregator.GetEvent(Of EventA).Subscribe(AddressOf OnSomeEventA)
There was a private function in the same class called OnSomeEventA that had some logic in it.
My question here is that how is everything wired over here? What exactly is achieved by the 'Publish' 'Subscribe' here? When 'something' changes, how does the compiler know it has to follow the logic in OnSomethingChanged that will 'Publish' an event that is 'Subscribed' by another class where the logic of the event handler has been described? It will be great to understand the underlying wiring of this process.
Thanks

The first time GetEvent<T> is called for each event (identified by the type parameter T) the EventAggregator creates an empty list of methods to call when that event is published. Typically, this will happen immediately before the first call to Publish or Subscribe (as in your examples).
Then:
Whenever Subscribe is called a method is added to the list.
Whenever Publish is called it walks through the list and makes those calls.
So, the call to Publish() in Presentation A results in all of the methods that have been registered by calling Subscribe being called, which in your example would include Presentation B's OnSomeEventA method.
Try setting a breakpoint in the OnSomeEventA method and take a look at the stack, and don't forget the source is available, too!

Related

Caliburn.Micro return result from child view model

So I have a ViewModel which contains logic to select a person from a list and if the person to be selected is not in the list a list item to open a new dialogue to create said person.
My problem is: How can I create the person in the child view model and get it in the parent. I searched (a lot) and found nothing satisfactory.
As far as I know there are at least three possibilities:
1. Use CMs EventAggregator to send messages to the Parent (and everyone else listening)
2. Use a property on the child VM and access this after the WindowManger has closed the Dialogue.
3. Implement IResult
I already did the first one, but this is (as said) not satisfactory. I don't want everyone to get the result, just because he listens to the EventAggregator. The second one is (in my view) not very MVVM like (or is it?), since i cannot control it if it is async.
As far I can tell from CMs doc, the third option is the preferred way. However I found no explanation how to adapt it to my solution.
I have to get user input and this is not possible in the Execute(CoroutineExecutionContext context) method.
Am I overlooking something or is the second method really the best way to achieve this?
2nd method is perfectly ok I have some situations where and I need a response result to proceed and get it upon closure of the view associated with the viewmodel that I call in a different method call, it could be done with a service specifically designed to grab results, if you are looking for S.O.C to avoid conflicts later. The 1st method is actually something I use for a few things, except I directly control what can see the message (new class object to watch for) and the only screens that can react to the message will do something.. 3rd is extremely powerful but I haven't ever actually got into the CoRoutines usage, it was the answer to async before async/await were available. There are lot of IResult examples floating around

Silverlight hangs on Prism's EventAggregator Subscribe method

I am using Prism's event aggregator in Silverlight and am having a hard time with Subscribe. When the code hits the Subscribe method it just hangs and never makes it to the next line of code. If I break up the code, _eventAggregator.GetEvent() seems to return a valid instance of the event. The code definitely hangs on "Subscribe". What could I be doing wrong here? The JobCompletedEvent is declared in another library (which is a dependency for this library).
public void CallMeWhenTheJobIsDone(Action callback)
{
if (_jobIsRunning)
_eventAggregator.GetEvent<JobCompletedEvent>().Subscribe((e) => callback(), ThreadOption.UIThread);
else
callback();
}
public class JobCompletedEvent: Microsoft.Practices.Prism.Events.CompositePresentationEvent<JobCompleted>
{ }
public class JobCompleted
{
}
1) Why you using if (_jobIsRunning) ?? You calling callback in any case.
2) Prism will only bring you the event - and according to your question - Prism IS rising and passing the event to you - so it's not a Prism question - it seems that whatever called by callback is not working.
So we need to see more on what is called by callback and another thing: in Prism case you calling the callback on ThreadOption.UIThread ThreadPool so - double check if any other thread already lock the UI thread when you calling callback
My problem is that I should not have used an anonymous method in my subscribe. Prism does not seem to support it. Some are calling this a bug in Prism, I agree :) Not only can you not use an anonymous method but the method must be public.
Some references I found googling
http://greenicicleblog.com/2010/04/28/prism-event-aggregator-more-leaky-than-it-seems/
Execute same Prism Command from different ViewModels
I suspect this is in the Prism docs somewhere, I guess I just blew by it. If I set keepSubscriberReferenceAlice it works with the private method or anonymous method (which does make some sense now that I think about it). The funny thing is that in my sandbox project I cannot even compile with an anonymous method which uses privately scoped code. My live project allows it to compile but fails at runtime.
Edit:
Yup, it is in the docs
http://msdn.microsoft.com/en-us/library/ff921122%28v=pandp.40%29.aspx
Big yellow box 2/3 of the way down the page.

Asynchronous WCF Services in WPF - events

I am using WCF services asynchronously in a WPF application. So I have class with all the web service. The view models call the method in this proc, which in-turn calls the web service.
So the view Model code looks like this:
WebServiceAgent.GetProductByID(SelectedProductID, (s, e)=>{States = e.Result;});
And the WebService agent looks like:
public static void GetProductByID(int ProductID, EventHandler<GetProductListCompletedEventArgs> callback)
{
Client.GetProductByIDCompleted += callback;
Client.GetProductByIDAsync(ProductID);
}
Is this a good approach? I am using MVVM light toolkit. So the View Model static, so in the lifetime of the application, the view model stays. But each time the view model calls this WebServiceAgent, I think I am registering an event. But that event is not being unregistered.
Is this a problem. Lets say the view Model is called for 20 - 30 times. I am inserting some kind of memory leak?
Some helpful information, based on the mistakes I learned from myself:
The Client object seems to be re-used all the time. When not unregisering event handlers, they will stack up when future invokations of the same operations finish and you'll get unpredictable results.
The States = e.Result statement is executed on the event handler's thread, which is not the UI dispatcher thread. When updating lists or complex properties this will cause problems.
In general not unregistering event handlers when they are invoked is a bad idea as it will indeed cause hard to find memory leaks.
You should probably refactor to create or re-use a clean client, wrap the viewmodel callback inside another callback that will take care of unregistering itself, cleaning up the client, and invoking the viewmodel's callback on the main dispatcher thread.
If you think all this is tedious, check out http://blogs.msdn.com/b/csharpfaq/archive/2010/10/28/async.aspx and http://msdn.microsoft.com/en-us/vstudio/async.aspx. In the next version of C# an async keyword will be introduced to make this all easier. A CTP is available already.
Event handlers are death traps and you will leak them if you do not "unsubscribe" with "-=".
One way to avoid is to use RX (Reactive Extensions) that will manage your event subscriptions. Take a look at http://msdn.microsoft.com/en-us/data/gg577609 and specifically creating Observable by using Observable.FromEvent or FromAsync http://rxwiki.wikidot.com/101samples.
This is unfortunaltely not a good approach.
I learned this the hard way in silverlight.
Your WebserviceAgent is probably a long-life object, whereas the model or view is probably short-life
Events give references, and in this case the webservice agent, and wcf client a reference to the model. A long lifeobject has a reference to a short life object, this means the short life object will not be collected, and so will have a memory leak.
As Pieter-Bias said, the async functionality will make this easier.
Have you looked at RIA services? This is the exact problem that RIA services was designed to solve
Yes, the event handlers are basically going to cause a leak unless removed. To get the near-single line equivalent of what you're expressing in your code, and to remove handlers you're going to need an instance of some sort of class that represents the full lifecycle of the call and does some housekeeping.
What I've done is create a Caller<TResult> class that uses an underlying WCF client proxy following this basic pattern:
create a Caller instance around an existing or new client proxy (the proxy's lifecycle is outside of the scope of the call to be made (so you can use a new short-lived one or an existing long-lived one).
use one of Caller's various CallAsync<TArg [,...]> overloads to specify the async method to call and the intended callback to call upon completion. This method will choose the async method that also takes a state parameter. The state parameter will be the Caller instance itself.
I say intended because the real handler that will be wired up will do a bit more housekeeping. The real callback is what will be called at the end of the async call, and will
check that ReferenceEquals(e.UserState, this) in your real handler
if not true, immediately return (the event was not intended to be the result of this particular call and should be ignored; this is very important if your proxy is long lived)
otherwise, immediately remove the real handler
call your intended, actual callback with e.Result
Modify Caller's real handler as needed to execute the intended callback on the right thread (more important for WPF than Silverlight)
The above implementation should also have separate handlers for cases where e.Error is non-null or e.Cancelled is true. This gives you the advantage of not checking these cases in your intended callback. Perhaps your overloads take in optional handlers for those cases.
At any rate, you end up cleaning up handlers aggressively at the expense of some per-call wiring. It's a bit expensive per-call, but with proper optimization ends up being far less expensive than the over-the-wire WCF call anyway.
Here's an example of a call using the class (you'll note I use method groups in many cases to increase the readability, though HandleStuff could have been result => use result ). The first method group is important, because CallAsync gets the owner of that delegate (i.e. the service instance), which is needed to call the method; alternatively the service could be passed in as a separate parameter).
Caller<AnalysisResult>.CallAsync(
// line below could also be longLivedAnalyzer.AnalyzeSomeThingsAsync
new AnalyzerServiceClient().AnalyzeSomeThingsAsync,
listOfStuff,
HandleAnalyzedStuff,
// optional handlers for error or cancelled would go here
onFailure:TellUserWhatWentWrong);

Non-blocking lazy-loaded properties in model of MVVM

I'm fairly new to MVVM, so please excuse me if this problem has a well-known solution.
We are building a bunch of model classes which have some core properties that are loaded up-front, as well as some additional properties which could be lazy-loaded on demand by making a web API call (update: to clarify, it would be a web API call per lazily-loaded property).
Rather than having multiple models, it seems sensible to have a single model with the lazy-loading logic in there. However, it also seems that the lazy-loaded properties should not block when accessed, so that when the View binds to the ViewModel and it binds to the Model, we don't block the UI thread.
As such, I was thinking of a pattern something along the lines of when a lazy property on the Model is accessed it begins an asynchronous fetch and then immediately returns a default value (e.g. null). When the asynchronous fetch is complete, it will raise a PropertyChanged event so that the ViewModel/View can re-bind to the fetched value.
I've tried this out and it seems to work quite nicely, but was wondering:
Are there any pitfalls to this approach that I haven't found out about yet, but will run into as the app increases in complexity?
Is there an existing solution to this problem either built into the framework, or which is widely used as part of a 3rd party framework?
I did something like this in the past and the one thing I kept forgetting about is you can't call your async property through any kind of code behind and expect it to have a value.
So if I lazy-load a list of Customer.Products, I can't reference Customer.Products.Count in the code-behind because the first time it's called the value is NULL or 0 (depending on if I create a blank collection or not)
Other than that, it worked great for the bindings. I was using the Async CTP library for making my async calls, which I found was absolutely wonderful for something like this.
public ObservableCollection<Products> Products
{
get
{
if (_products == null)
LoadProductsAsync();
return _products;
}
set { ... }
}
private async void LoadProductsAsync()
{
Products = await DAL.LoadProducts(CustomerId);
}
Update
I remember another thing I had issues with was data that actually was NULL. If Customer.Products actually returned a NULL value from the server, I needed to know that the async method had run correctly and that the actual value was null so that it didn't re-run the async method.
I also didn't want the async method to get run twice if someone called the Get method a 2nd time before the first async call had completed.
I solved this at the time by having an Is[AsyncPropertyName]Loading/ed property for every async property and setting it to true during the first async call, but I wasn't really happy about having to create an extra property for all async properties.

Making actions get called in silverlight unit test with MOQ

Lets say I have this
_articlesService.SaveAsync(Model, AddressOf OnSaveCompleted)
The OnSaveCompleteMethod do a couple of things, obviously. Its a
Protected Overridable Sub OnSaveCompleted(ByVal asyncValidationResult As AsyncValidationResult)
In my unittest. I need to run a mocked SaveAsync, and have OnSaveCompleted called in anyway, because the method sends out events that I need to know have been sent.
Right now, the code just walks past that method, thus its never executed.
Need help solving this because I'm stuck right now.
If I understand your context right:
you have a class under test which uses an ArticlesService
your ArticlesService (a collaborating class) is responsible for sending some events
you want to verify that your class under test is behaving correctly
you want to do that by checking for the events.
If that's the case, you may be making your class responsible for more than it needs to be. You only need to verify that the ArticlesService was asked to SaveAsync. You don't need to worry about what the ArticlesService then went off and did.
Think of it this way. You are a Class-Under-Test. You have too much work to do, so you've asked some other people to help you. You have two choices. You can either chase them up, worrying about whether they're doing it right, or you can just trust them.
Rather than micro-managing classes, you can write a separate test which gives some examples of the way the ArticlesService will work, which will check that the ArticlesService is doing its job correctly. Your CUT's responsibility is to delegate that work effectively.
If you actually need the events to be raised so that your CUT can respond, that's a separate aspect of its behaviour, and you can do it with Moq's "Raise" method, documented in "Events", here:
http://code.google.com/p/moq/wiki/QuickStart
Edit: You can also use "CallBack", documented on the same link, to do stuff with the args being passed to you, including OnSaveCompleted. Not sure if it's going to help or not; it's tricky to see what you're doing without both the code and the failing test. Good luck anyway!
Close, but not exactly like that.
We don't actually send out an event in the ArticleService.
The method SaveAsync takes an Article to be saved, and a method to be called once the saving is complete.
The problem is that the "OnSaveCompleted"-method isnt being called. (This method exists in the View Model Base class, so the service isnt sending the event, the viewmodel is.).
But we have our own implementation of WCF-service proxies so this is probably what's messing with us, since we dont use the generated code.
Think we will have to rework our infrastructure on the services abit to solve this.
So it's a special case, just wanted to throw the question out just in case. :)
Thanks anyway for the answer.

Resources