Skip to content

Uses of Action<T>: The Return-to-Sender Pattern

January 29, 2012

The Action<T> generic delegates can often be used to make difficult code appear simple.  This holds as well for its cousin the Func<T,TResult> generic delegate that returns a result.  This article explores one simple but powerful use of the Action<T> delegate:  The Return-to-Sender pattern.  In doing so, it also demonstrates the effectiveness of using this pattern with the Prism EventAggregator events in monolithic, tightly coupled, legacy code.

Purpose

The purpose of the Return to Sender pattern is to provide a simple way for a Presentation Layer event subscriber to return information to the Presentation Layer publisher of the event.

This is purely a Presentation Layer pattern to facilitate limited 2-way communication between various objects that do not have a reference to each other, and which would take a lot of code changes to provide the references required to do normal procedure calls.  A typical usage scenario is where there is a deeply nested control that needs 2-way communication with another control that resides “outside the nest”, so to speak.

The Return to Sender pattern features an event whose event args contain an Action<T> callback.  The Action<T> callback is a method injected into the event args by the publisher, and thus is available for invocation by the event subscriber.  This callback’s argument(s) provides the event subscriber a means to return information to the publisher of the event.

The Return-to-Sender pattern works extremely well when modifying large tightly coupled monolithic legacy code bases when the pattern is used with Prism’s Event Aggregator events that require no reference between publisher and subscriber. This allows information to be exchanged between publishers and subscribers at any place in the code base, no matter how deeply nested within other controls a publisher may be and no matter how tightly coupled the code base is.

Yes, the Return-to-Sender pattern can be considered to be a hack.  But in situations where there is not enough time allocated to “do it right” it is a decent choice since it does use loose coupling and is very quick to implement.

Other loosely coupled event aggregator functionality can also be used with the Return-to-Sender, as found in MVVM Light, Jounce, and Caliburn.  Brian Noyes’ has a good explanation and example of how to use the Prism EventAggregator at http://www.silverlightshow.net/items/Working-with-Prism-4-Part-3-Composite-Command-and-Pub-Sub-Events.aspx

How it Works

The publisher of the event deposits the name of one of its own methods matching the Action<T> signature into the event args Callback property, of type Action<T>.  It subsequently raises the event.

A subscriber to the event receives the event in its event handler.  The subscriber instantiates the type T that is the Callback’s argument, then deposits the required information into the properties of the type T.  Finally the subscriber invokes the Action<T> Callback, resulting in the event publisher’s Callback method being invoked with the argument(s) supplied by the event subscriber.  The implementation is straight forward to understand and simple to use as the following code example shows.

Code Example

The code example may be downloaded from the file named  BasicReturnToSender on OneDrive.  Just click the link, then click “Download” on OneDrive’s top menu bar when it appears.

Please note that the example code does NOT use MVVMs since it simulates legacy code.  Hence all User Control code is in the code behind.  It’s better to use MVVMs, but this is a simulation.

The code example (a Silverlight 5 app) shows the complete implementation of the Return-to-Sender pattern in a situation in which a nested control (publisher) needs to ask a control that is “outside the nest” (subscriber) for some information.

First, take a look at the xaml of the MainPage that is the center stage for the example.

Specifically note that, the nested FeatureAView (publisher) needs to ask the MainPage (subscriber) for the width of the right part of a Grid that is divided into the right and left content areas, each residing in its own Grid.Column.  The widths of the 2 content areas (i.e. Grid columns) are dynamic since the Grid has a GridSplitter to allow the user to adjust the widths.  It would be user friendly to save the grid column width of the right content area to disk when the user exited this app, so it could be set on the next app start. The code example does not show how to save the column width to disk nor how to restore the column width on start up.  It only shows how to get the grid column width from the MainPage.

If there was really deep nesting of controls in the leftContentArea, the Return-to-Sender pattern provides a quick, loosely coupled was to communicate with the MainPage to get the Grid column width of the rightContentArea.  Note that the example does not have deep nesting of controls for reasons of simplicity.  However, the implementation of the Return-to-Sender pattern is the same, nevertheless.

The pattern implementation requires that the Common project be added to the original solution, plus some other code.  You’ll see the newly added Common project in the Solution Explorer, as follows:

The Common project contains a static instance of the Prism EventAggregator, plus the class GetWidthOfRightContentAreaEvent which implements this Prism event.  To see the code in the event publisher and subscriber, open GetWidthOfRightContentAreaEvent.cs and right click on the class name GetWidthOfRightContentAreaEvent.  From the Context Menu, select “Find all References” and you will see the code for the event declaration, for the publisher in FeatureAView.xaml.cs, and for the subscriber in MainPage.xaml.cs.

I will not bore you with an explanation of how this works.  It should be self-evident when you run the app under the Visual Studio debugger using the breakpoints listed below.

In the subscriber, MainPage.xaml.cs place breakpoints as follows:
Line 26, in MainPage() constructor where the event subscription is done.
Line 46, in ReturnWidthOfRightContentAreaToSender()

In the publisher, FeatureAView.xaml.cs place breakpoints as follows:
Line 29, in GetWidthButton_Click()
Line 34, in DisplayWidthOfRightContentArea()

So, take a few minutes to inspect the code.  Then press F5 and you’re off and running with a new pattern to aid you in dealing with messy, time consuming situations in legacy Silverlight code.

Creative Commons License
dotnetsilverlightprism blog by George Stevens is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Based on a work at dotnetsilverlightprism.wordpress.com.

Advertisements
Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: