This is a known issue with using composite presentation events from Prism in Silverlight. It’s a side affect of the weak referencing used internally by the event aggregator. Weak references are used to reduce memory leaks, which is a big plus point of using the event aggregator. The reason you get this exception with Silverlight (and not WPF) is because there is no private reflection support. Private reflection is used indirectly because the weak reference taken is to delegate.Target (See DelegateReference). If the target is a private method, then you won’t be allowed invoke it. The code below is an example:
Work around is simple, make that method public. But, I don’t want to make it public. I want my ViewModel API to be what I want it to be, not what the Event Aggregator needs it to be. So how do I work around this?
What we need to do is adapt a private method to a public method so it can be invoked:
Now you can use that class in the subscription. Note the code below must have a reference to the EventSubscriptionAction. Remember it’s a weak reference the Event Aggregator is holding, so if you don’t have a reference in your class the target could be null.
An interesting side affect of this is you now don’t actually need a method, you can use a lambda (shown below). This again reduces the friction of subscribing to an event.
But, we can do a bit more. I don’t want to have to new up a EventSubscriptionAction and I don’t want to have to worry about making sure I keep a reference. Obviously, I still must keep a reference and tie the lifetime of that reference to the lifetime of the owning class (i.e. the ViewModel), otherwise I’ll create a memory leak.
Now what I can do is pull out the Subscribe method and put it in a class which I can reuse.
One last step you could do is put it on your base ViewModel (if all your view models deal with event subscription then it might make sense).
So now you can use the event aggregator and have private methods. The added bonus is if you want to use it inline without the private method you don’t need to worry about holding a reference each time you do it.
I thought I’d share this as I’ve seen a few times now public methods which really shouldn’t be public. I’ve also seen a lot of one line privates which could well be expressed better with a lambda. It’s a simple step to making view model code more readable. I also thought it was a nice example of how something simple evolves into something useful. It’s a nice simple example of layering functionality. Of course, I may well be missing something, so if anyone has an alternative approach please share!