当前位置 > 首页 > Asp.net

MVVM Mediator Deluxe

2009-10-7 10:53:00来源:Asp.net

From what I’ve been reading on the implementations of the Mediator pattern for MVVM, I must say I’m a little disappointed. Maybe it’s my background with a certain UI design methodology (for which I must credit Philip Almey, a former colleague) for the last five or six years. Using (hierarchic) state charts to design user interfaces allows you to think about it’s behavior without being hampered by technology nor content or style. I’m happy that this “way of thinking” still stands firm as technology progresses (into Silverlight/WPF that is). Translating such charts into the asynchronous code flows that rule the “new world” is a challenge. One that requires clear separation of concerns, and the MVVM pattern adds a lot of value to solve this challenge. Another piece of the puzzle is the EventAggregator (Prism term) / Mediator / Message Bus / Messenger that provides the communication mechanism between your views and view models. But current implementations seem to focus on using the mediator as a publish/subscribe pattern vehicle and going to great lengths to eliminate memory leaks (which I personally find a little over the top considering that “unsubscribe” should be something explicit).

Looking at the mediator communication mechanism from a messaging perspective, I see a lot of room for improvement. There is no explicit concept of addressability (think WS-Addressing). If I want to send a message to a specific view, I’ll have to juggle with predicates and properties to make it work. Mind you I’m not advocating for tightly coupling views and view models (although some implementations already do this on subscription ;-)). After all, for addressability, one can simply use System.Uri. Along with addressability comes explicit support for the request/response message exchange pattern (alongside the existing publish/subscribe pattern). I’d like to see an API along the following lines:

//Receive any message of the specified type
IDisposable Accept<TRequest>(RequestCallback<TRequest> callback) where TRequest : RequestMessage;

//Receive messages of the specified type matching the predicate
IDisposable Accept<TRequest>(Expression<Predicate<TRequest>> predicate, RequestCallback<TRequest> callback) where TRequest : RequestMessage;

//Reply to a request message
void Reply<TReply>(TReply reply) where TReply : ReplyMessage;

//Send a request message
void Request<TRequest, TReply>(TRequest request, ReplyCallback<TReply> callback)
    where TRequest : RequestMessage
    where TReply : ReplyMessage;

Remark: People who have used WSE3 (yes, really) will know that you can use the message to specify the addressing bits.

I know this API is more rigid (contrary to sprinkling Action<T>) but that’s also its strength. It forces you to think in terms of request/reply messages that flow around. This is how I discovered that sequence diagrams are the new hype all over again to model the communication between views and view models and how they help me understand the message flow. I realize that there are a lot of details and mechanics about the API that I haven’t explained, but this post is just intended to get the juices flowing.

My conclusion: Is it impossible to achieve the above with the current incarnations? No, but it’s cumbersome and too verbose.