Monday, December 21, 2009

Decoupled ViewModel Messaging (Part 3)

NOTE: All the code shown in this series has been published to codeplex. If you would like to download the framework or the sample application that uses the framework you can find it here: http://courier.codeplex.com/

    In this part of our saga we find or intrepid hero trapped in a ……. Wait where was I? So far in this series we have covered decoupled messaging between ViewModels at a high level and we have looked at one specific enhancement that I have added to my courier framework that is lacking in other implementations.

     In this final post I am going to cover one more feature that I have added to the courier framework that I think provides a very nice addition to the overall process of decoupled ViewModel messaging and that is message caching.

    When I first started with this framework I really just set out to wrap my head around what others had done (CoreMVVM,Cinch, Prism, MVVM Foundation). Once I had gotten to that point I wanted to add a little something more to make the framework my own. What I found was that, in my scenarios, I found myself needing to cache messages for later retrieval. 

    The most obvious case for this is in the “Wizard” type scenario. When a user is performing a sequential set of actions I often have the need to pass data from one screen to the next. In this scenario the next screen is not created until after the previous screen is destroyed. This means that the message broadcast from screen one would happen before screen two is around to listen for it. With me so far?

    So, to solve this problem I figured I would implement some sort of caching mechanism that would allow me to:

  • Broadcast a message from View one
  • Save the message for re-broadcast
  • Destroy View one
  • Create View two
  • Register for that message from View two
  • Receive any, valid, cached copies of the message I registered for

The first thing I did was to implement an internal List<T> inside the mediator class that would store these CachedMessage objects. When a message is broadcast with caching options I will save a copy of the message to this List<T>. Any subsequent registrations for this message will receive any valid cached copies of the messages.

    So I added the following to the mediator

private readonly List<CachedMessage> cachedMessages = new List<CachedMessage>();


Where the CachedMessage class is defined like this:



[DebuggerDisplay("Message: {Message}, Parameter: {Parameter}")]
internal class CachedMessage
{
public String Message { get; private set; }
public Object Parameter { get; private set; }
public CacheSettings CacheOptions { get; private set;}
public Int32 ResendCount { get; set; }

public CachedMessage(String message, Object parameter)
{
Message = message;
Parameter = parameter;
}

public CachedMessage(String message, Object parameter, CacheSettings cacheOptions)
{
CacheOptions = cacheOptions;
Message = message;
Parameter = parameter;
}
}


    Two things to note here. First the CachedMessage class has a public property of type CacheSettings. This gives us the details of how long to keep the message for. Currently I am supporting two types of caching, time based and recurrence based. This means you can specify a specific DateTime when the message will expire or you can specify how many re-broadcasts before the message expires. The CacheSettings class looks like this:



[DebuggerDisplay("Expiration Date: {ExpirationDate}, NumberOfResends: {NumberOfResends}")]
public class CacheSettings
{
public DateTime ExpirationDate { get; private set; }
public Int32 NumberOfResends { get; private set; }

public CacheSettings(DateTime expiration)
{
ExpirationDate = expiration;
NumberOfResends = Int32.MaxValue;
}

public CacheSettings(Int32 timesToResend)
{
NumberOfResends = timesToResend;
ExpirationDate = DateTime.MaxValue;
}
}


    The second thing to note about both of these classes (CachedMessage and CacheSettings) is the use of the DebuggerDisplay attribute. I have just recently got in the habit of using this attribute religiously and I don’t know what I ever did without it. I won’t dive too in depth here about it, but suffice it to say, if you aren’t using it right now you should be. If you don’t know what it is stop reading here and jump over to my colleague, Adam Calderon’s, excellent post about it (don’t worry I will wait for you to come back).



    Ok, now that we are all writing Debugger friendly classes thanks to Adam, let’s wrap this post up with some usage scenarios. In the “Wizard” like case I talked about above I really just want to be able to broadcast a message and cache it for one re-broadcast. This allows me to broadcast the message from view one and then destroy view one and create view two. view two then registers for the message like it would normally and will immediately receive any messages that are in the cache. Once the message is dispatched from the cache we want to clean it out to prevent further re-broadcast. So first, two examples of how to call BroadcastMessage<T> with caching options



//NumberOfResend based caching example
Mediator.BroadcastMessage("Content1Message",messageContent,new CacheSettings(1));

//Time Based caching example
Mediator.BroadcastMessage("Content1Message", messageContent, new CacheSettings(DateTime.Now.Add(TimeSpan.FromSeconds(30))));


The first example show how to broadcast a message and specify that it should be cached for one re-broadcast. The second example shows how to broadcast a message and store it in the cache for 30 seconds after the first broadcast. Pretty straightforward so far. Now the two key methods in the Mediator class that handle keeping the cache clean and dispatching messages from cache:



private void GetMessagesFromCache(String message, Delegate callback)
{
CleanOutCache();
//Search the cache for matches messages
List<CachedMessage> matches = cachedMessages.FindAll(action => action.Message == message);
//If we find matches invoke the delegate passed in and pass the message payload
matches.ForEach(delegate(CachedMessage action)
{
callback.DynamicInvoke(action.Parameter);
action.ResendCount++;
});
}

private void CleanOutCache()
{
//Remove any expired messages from the cache
cachedMessages.RemoveAll(message => (message.CacheOptions.ExpirationDate < DateTime.Now) || (message.ResendCount >= message.CacheOptions.NumberOfResends));
}


    You can see in the GetMessagesFromCache method the first thing it does is clean out any expired messages from the cache. The CleanOutCache method uses the RemoveAll method on List<T> and an lambda to do a particularly elegant line of code. This code checks two properties of the CachedMessage objects (is it’s expiration date in the past OR has it been re-broadcast the max number of times?). If either is true it is removed from the CachedMessages list. A very succinct line of code for a normally cumbersome task.



    After the cache has been cleaned we call FindAll (again, using a simple lambda) to get all the messages from cache that match the one we are looking for (There could be multiple messages from different senders in the cache and we want to dispatch them all). Once we have the matching messages we invoke the callback that is registered and we increment the re-send count on the message. Overall, a pretty simple process, but it turns out to be very powerful.



    That wraps up this 3 part series ( I, II, III) on the Courier framework. As I add new features to the framework I will post specific updates about the features. If anyone else is interested in joining the codeplex project and adding their ideas to the framework please feel free to contact me through this blog.  



NOTE: All the code shown in this series has been published to codeplex. If you would like to download the framework or the sample application that uses the framework you can find it here: http://courier.codeplex.com/

Labels: , , , , ,

Tuesday, November 17, 2009

Decoupled ViewModel Messaging (Part 1)

 

NOTE: All the code shown in this series has been published to codeplex. If you would like to download the framework or the sample application that uses the framework you can find it here: http://courier.codeplex.com/

Lately I have been playing around with different ways to decouple the communication between ViewModels in the MVVM pattern. My focus has been in WPF, as this is what the MVVM pattern is suited for however, this messaging technique is not specific to WPF and could be used in any other decoupled solution (MVC, MVP etc..)

I poked around on the tubes looking for examples of how other people have solved this problem and there are many different options out there. My implementation borrows heavily from the CoreMVVM framework on codeplex which itself borrows bits from Cinch, Prism, MVVM Foundation etc.. 

My first goal was to really just get down in the weeds and understand how these other frameworks were handling decoupled messaging between objects. Once I wrapped my head around it I then came up with two features that I thought would be nice to have in a messaging solution that I hadn’t seen in other frameworks.

The ability to manually unsubscribe from messages and the ability cache messages for re-broadcast.

Before I dive in and talk about the new features I wanted to add let me go over the basic implementation of the Mediator pattern I did. Again, this is very similar to how the CoreMVVM framework does it, so if you are familiar with that framework this should review.

The basis of the implementation is a basic mediator pattern. You have a mediator object that stores a mapping of subscribers and messages. This gives the mediator enough information to understand what messages to dispatch to what subscribers. The mediator in my case looks like this 

//Method bodies elided for clarity
public class Mediator
{
private readonly MessageToSubscriberMap subscribers = new MessageToSubscriberMap();
private readonly List<CachedMessage> cachedMessages = new List<CachedMessage>();

public void RegisterForMessage(String message, Delegate callback)
{
...
}

public void UnRegisterForMessage(String message, Delegate callback)
{
...
}

public void BroadcastMessage<T>(String message, Boolean cacheMessage, T parameter)
{
...
}

public void BrodcastMessage<T>(String message, Boolean cacheMessage)
{
...
}

private void GetMessagesFromCache(String message, Delegate callback)
{
...
}
}


From the snippet above you can see there isn’t much going on in the Mediator. The key is really the MessageToSubscriberMap object defined at the top. This object is what stores the (weak) reference to the subscriber (in this case a delegate to be invoked) and the message that subscriber is interested in.



Here are the guts of the MessageToSubscriberMap class



//Method bodies elided for clarity
internal class MessageToSubscriberMap
{
//Store mappings with weak references to prevent leaks
private readonly Dictionary<String, List<WeakSubscriber>> map = new Dictionary<String, List<WeakSubscriber>>();
internal void AddSubscriber(String message, Object target, MethodInfo method, Type subscriberType)
{
...
}

internal void RemoveSubscriber(String message, Delegate callback)
{
...
}

internal List<Delegate> GetSubscribers(String message)
{
...
}
}


The key piece of this map is the private Dictionary field. This is the mapping of Messages to the collection of WeakSubscribers that are listening for that message. I have called the object WeakSubscriber to indicate that a subscriber is really a WeakReference to a delegate. Here is the complete implementation of the WeakSubscriber class



internal class WeakSubscriber
{
private readonly MethodInfo method;

public MethodInfo Method { get { return method; } }

private readonly Type delegateType;
private readonly WeakReference weakReference;

internal WeakSubscriber(Object target, MethodInfo method, Type parameterType)
{
//create a WeakReference to store the instance of the target in which the Method resides
weakReference = new WeakReference(target);
this.method = method;
delegateType = parameterType == null ? typeof(Action) : typeof(Action<>).MakeGenericType(parameterType);
}

internal Delegate CreateAction()
{
Object target = weakReference.Target;
return target != null ? Delegate.CreateDelegate(delegateType,weakReference.Target,method) : null;
}

public Boolean IsAlive
{
get { return weakReference.IsAlive; }
}

}


Ok so now we have seen the extent of my little messaging framework. Again, most of this code is very similar to the CoreMVVM framework implementation of the mediator pattern so, for users of that framework, this should be familiar.



I am going to wrap this post up with a quick example of how you would subscribe to a message and how you would broadcast a message with this framework.



To broadcast a message you would do this:



Mediator.BroadcastMessage("Content1Message",true, messageContent);


Note the second parameter in this method call is for caching the message which I will explain in a following post.



If you wanted to subscribe to this Content1Message you would register for the message like this:



Mediator.RegisterForMessage("Content1Message", (Action<String>)OnContent1MessageReceived);


In the next post I am going to describe the two new features I added to the framework which are the ability to unsubscribe from a message and the ability to cache messages for re-broadcast.



This project was built in Visual Studio 2010 Beta 2, If you haven’t already I highly recommend downloading VS2010



As a side note, the specific reason I using VS2010 is because I plan on parallelizing the dispatching of messages to subscribers in the future and want to use the new parallel framework in .NET 4.0 



NOTE: All the code shown in this series has been published to codeplex. If you would like to download the framework or the sample application that uses the framework you can find it here: http://courier.codeplex.com/

Labels: , , , , ,

Friday, October 16, 2009

Seeing Stars I’m Seeing Stars

“Oh my, starry eyed surprise. Sun down to sun rise. Dance all night. We gonna dance all night…”

Feel free to stab your eyes out at this point (Or drink a Diet Coke)

Ok so WTF am I talking about? Custom Ink Canvas rendering in WPF of course… I ran across a problem recently that I thought was blog worthy. The objective was to allow a user to draw on an InkCanvas with a custom “stencil.” The “stencil” is really just some custom shape that should be used as the stroke for the InkCanvas. This is kind of hard to explain so a picture may help

SurfaceCustomInking[1]

In this picture the stars (hence the terrible Oakenfold reference) would be the stencil. When the user drags the mouse around the canvas we want to draw the stars like shown above. This isn’t quite as obvious to implement as most things in WPF. My hope was that I could just set the Stroke to some DrawingBrush and be done. However, it isn’t that easy.

The main reason for the complication is the way that the InkCanvas collects the strokes from the user. The strokes are are collected on a background thread to ensure that all strokes will be collected, even if the UI is blocking. This is done through a DynamicRenderer object. This object collects the user input and renders all points in the stroke on a separate thread.  Once the entire stroke is collected The InkCanvas raises the OnStrokeCollected method.

The first step to solving my problem is to implement a custom DynamicRenderer  that will track the users movements on the canvas and render our custom shape along the path that the user has drawn.

public class CustomRenderer : DynamicRenderer
{
private Point prevPoint;

public DrawingGroup Stencil { get; set; }

protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
// Allocate memory to store the previous point to draw from.
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
base.OnStylusDown(rawStylusInput);
}

protected override void OnDraw(DrawingContext drawingContext,StylusPointCollection stylusPoints,Geometry geometry, Brush fillBrush)
{
for (int i = 0; i < stylusPoints.Count; i++)
{

var pt = (Point)stylusPoints[i];
Vector v = Point.Subtract(prevPoint, pt);

// Only draw if we are at least 4 units away
// from the end of the last ellipse. Otherwise,
// we're just redrawing and wasting cycles.
if (v.Length > 4)
{
var clone = Stencil.Clone();
clone.Transform = new TranslateTransform(pt.X, pt.Y);
drawingContext.DrawDrawing(clone);
prevPoint = pt;
}
}
}

}


The key to this snippet is in the OnDraw method override. I am iterating through the points along the path that the user has drawn then rendering a new instance of our custom drawing to the DrawingContext pipeline. Notice the TranslateTransform, I am using the translate to make sure the drawing I add to the DrawingContext pipeline follows the points in the path that the user created.



Once the stylus points are converted to strokes then the stroke is told to render itself. This is the second step in the process. We need to create a custom stroke class that renders our custom shape when it is asked to render itself.



class CustomStroke : Stroke
{
public DrawingGroup Stencil { get; set; }

public CustomStroke(StylusPointCollection stylusPoints) : base(stylusPoints)
{
}

protected override void DrawCore(DrawingContext drawingContext,DrawingAttributes drawingAttributes)
{
// Allocate memory to store the previous point to draw from.
var prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);

// Draw linear gradient ellipses between
// all the StylusPoints in the Stroke.
for (int i = 0; i < StylusPoints.Count; i++)
{
var pt = (Point)StylusPoints[i];
Vector v = Point.Subtract(prevPoint, pt);

// Only draw if we are at least 4 units away
// from the end of the last ellipse. Otherwise,
// we're just redrawing and wasting cycles.
if (v.Length > 4)
{
var clone = Stencil.Clone();
clone.Transform = new TranslateTransform(pt.X, pt.Y);
drawingContext.DrawDrawing(clone);
prevPoint = pt;
}
}
}
}


You can see the DrawCore method looks very similar to the OnDraw method in the custom renderer. We are doing the same rendering in both places so the code will be very similar.



The final step in this process is to create a class that inherits from InkCanvas and wire up the dynamic renderer and the custom stroke.



public class CustomRenderingInkCanvas : InkCanvas
{
readonly CustomRenderer customRenderer = new CustomRenderer();

public CustomRenderingInkCanvas(): base()
{
// Use the custom dynamic renderer on the
// custom InkCanvas.
DynamicRenderer = customRenderer;
}

protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
{
// Remove the original stroke and add a custom stroke.
Strokes.Remove(e.Stroke);
var customStroke = new CustomStroke(e.Stroke.StylusPoints)
{
Stencil = Stencil
};

Strokes.Add(customStroke);

// Pass the custom stroke to base class' OnStrokeCollected method.
var args = new InkCanvasStrokeCollectedEventArgs(customStroke);
base.OnStrokeCollected(args);
}
}


I have cut out some code from the snippet above to focus on the important parts. The two keys are wiring up the DynamicRenderer in the public constructor and removing the default stroke and adding in our custom stroke in the StrokeCollected override



Once we put all these steps together we end up with an ink canvas that we can apply a custom stencil to and use that stencil to draw with.



The result is shown in the video below ( Turn on your sound ;)




Custom InkCanvas in WPF from Brad Cunningham on Vimeo.


Note: the lag you see in the video is just from me trying to draw using the trackpad on my laptop with one hand. The actual application doesn’t lag.

You can download the full sample project from here. I followed this MSDN article in solving this problem

Labels: ,

Wednesday, September 9, 2009

Random nerd debates

Working as an engineer means that you get involved in random nerd debates on (at least) a weekly basis.

Most of these debates are useless drivel that aren’t worth noting but occasionally a topic comes up that is worth some level of posterity. Since my blog is otherwise full of useless stuff I figure starting a series on nerd debates isn’t the worst thing I could do :) 

So episode 1 of the Random nerd debate series.

(Interestingly you will notice that SyntaxHighlighter doesn’t even understand the Class name syntax Boolean, but does understand the alias syntax)

bool


Vs.



Boolean


Or int Vs. Int32 or whatever you want to call it. I am pretty sure I am in the minority here but I tend to prefer using the class name syntax Boolean Vs. the alias syntax bool. It is mostly personal preference but I think there are two key areas where the distinction makes a difference.



First when you are calling static methods that live on the class it seems weird to me to use the alias syntax.



bool.TryParse()


doesn’t feel the same as



Boolean.TryParse()


Again, I think I am in the minority here. My thought is that when you are calling methods you are doing so on the class itself. Using the alias just adds a level of indirection, albeit a minor and mostly overlooked one.



The second place where I think class name syntax gives you a true benefit is in clarity. When using the alias syntax int I have heard several people think that Int32 is simply a implementation detail and that the alias int hides that from you. So if you were compiling on x64 int would translate into Int64 instead of Int32.



This is a misconception however the int alias is simply that, an alias, or syntactic sugar for Int32. If you want Int64 you have to use the alias long. Of course you could specify Int64 explicitly using class name syntax and be done with it.



The more 64 bit programming becomes the norm I think the more we will run into some confusion. Do you use int, or double, or float, or long etc…



Interestingly the alias double maps to the class Double but the alias float maps to the class Single (have you ever seen someone use Single in their code?) In a chat with a friend about this topic his response was



“I go with shorter just from habit, but would generally defer to the team standard. i.e. it's not an issue I feel strongly about, but do feel that a decision one way or another needs to be made on a project”



Generally I agree with that statement and I think team level consistency is important. I think in most cases you will see teams using the alias and I think, in most case, this works out fine for them. All programmers can read the alias and I think that some may even be confused at first if they see the ClassName syntax and haven’t seen it before but, to me, it increases clarity and intent.



Stack Overflow had a nice thread about this very thing that I found while poking around for this post



You can find a complete list of all the built in type aliases for .NET, and their equivalent class name here



In a bit of a contradiction of style I do however use the var keyword very often. Which may sound like it reduces code clarity but there are places in which I purposely want to abstract the implementation details of the backing type from my code. But that debate is for episode 2. Stay tuned.

Labels: , ,