When I was writing my last post I had a distinct feeling that I was trampling over some boundaries of good NAV design. After all, you should not do stuff like that, NAV isn’t meant to do things like that, or at least that was how I felt.
And then two things happened.
First, I asked myself: what the heck, why not? What exactly is NAV meant to do, and why not things like that? If folks at Vedbæk didn’t provide an out-of-the-box solution for the problem, why should the problem stay unsolved?
Second, my dear friend and a fellow MVP, Hrvoje of Hudo’s Vibe, identified the thing as the mediator pattern. So, the thing I’ve done to NAV, civilized world has been doing to their programming environments for a long time.
And then I decided to take it all to a different level altogether, and expand the simple class which didn’t do much but raise events on itself when its method was called, into a full-scale framework. And here it is, the mediator pattern incarnated into a brand new Dispatcher class, adapted to NAV, and with features that make it truly flexible. I do not dare starting to think what are all the situations where you could put this thing to use in NAV.
In a nutshell, the mediator pattern allows different objects to interact and exchange information, without them having to be aware of each other, or ever calling each other directly. To illustrate an NAV example, it would be as if you clicked Post on a sales invoice, and the action never invoked codeunit 80. Instead, the action invoked the Mediator object, telling it to post the sales invoice, and the Mediator object notified the object in NAV that was in charge of posting sales invoices, and that object then invoked codeunit 80. The whole pattern decouples the dependencies to the maximum and allows flexibility and versatility beyond anything we know of in NAV.
So, this Dispatcher object, which in itself is a .NET assembly that you can use through .NET Interoperability, enables this pattern by allowing objects to call the mediator class and asking it to dispatch the information to other objects. This information may be anything, and the mediator class would dispatch it to those other objects that are interested in that specific information.
So, here are the features in a nutshell:
- Dispatching information: when you need to notify other objects about something, you call the Dispatch method of the Dispatcher object. The message you are dispatching contains the information about the source, the target, and the data, all of which are optional.
- Subscribing to dispatch events: when an object dispatches information through the mediator, the mediator raises dispatch events in all instances of the Dispatcher object that subscribed to the Dispatched event.
- Source and Target checking: after you instantiate the Dispatcher object, you can register targets and subscribe to sources. When an event is dispatched with a source specified, then only those objects are notified that are subscribed to the source of the dispatch. Also, when an event is dispatched with a target specified, then only those objects are notified that have registered themselves as that target. You can combine sources and targets in the same dispatch events, and objects can register multiple targets, or subscribe to multiple sources.
- Cross-session: this is a bombshell. The whole thing works across NST sessions and allows you to dispatch events to other sessions as well. When dispatching, you can choose whether to dispatch just within your session, or to all sessions. Also, each object can choose whether it only listens to dispatches within its session, or to dispatches from all sessions.
At this stage this may sound quite abstract, but I’ll try to catch some time to create a couple of kick-ass demos for NAV 2013 that showcase the capabilities and the power of this simple framework.
I have a thousand ideas of what I want to do with this framework to make it even better, but some of those may make things more complicated for consumption within NAV. Right now, this is not NAV specific, you can use this in any .NET projects, but it was created with NAV in mind. I plan to add support for generics, to make the whole framework aware of the type of data being dispatched, and then notifying only those subscribers who are registered for handling that data type. This would reduce the amount of coding tremendously.
In any case, you can download the latest version on the link below, and I’ll make sure to post every updated version as soon as I have it ready:
Download VjekoCom.Dispatcher, Version 1.0.5140.4706.
Please let me know what you think of this version, as compared to the last one.
This Post Has 7 Comments
Thinking out of the box is very important and Patterns is a good way to go.
It is always difficult to find the right balance.
On one side you want to create fantastic and maintainable software. But at he same time you need to work within the scope of the NAV Framework. No doubt by pulling in a lot of .net, We can change NAV to an extend, where it is no longer NAV. It is a tough balance.
NAV has changed a lot with the past couple of releases and it becomes very clear that an update of Language, Framework and the IDE is long overdue.
Ideas like this with the Mediator, Facade and Strategy Patterns, indicates that at least a part of the NAV community is thinking out of the box. For a newbie that is refreshing. Keep up the good work.
It is a great post. Thank you for that and keep on publishing more about topics like this.
Beginning with NAV 2013 (R2) MS opens the NAV-World for doing senseful and necessary things by utilizing .net. You can do great stuff and extend NAV in a way that other environments can do naturally.
Anyway, years ago we used this pattern in a COM component to let the Classic Client communicate in a decoupled manner or the other way round bring more than one subform together., for example. We overcame boundaries to create a good solution for the customer. That’s the primary goal and legitimates almost any approach.
Hi Vjeko. Great post 🙂
Although I’ve been working with NAV for many years, using dotnet is still far from second nature. I would be interested in seeing an example of some CAL code showing how you use this, for example, how you specify source, target and data, and how you might handle your source and target checking.
Thanks for sharing!
this is interesting stuff. Thanks for taking the time to create this framework and share it. Personally I found the c# scary as – I’m not sure I understand half the syntax having never used delegates, lambdas, LINQ, events, etc., etc. Is there any way you could put some comments in the code for those of us that don’t work in c# regularly so we can understand what is going on? I’m OK with most of it, but the bit around public event DispatchEventHandler Dispatched, is a complete mystery to me. What’s all this add and remove stuff and where does it get used and how?
I’m also looking forward to some concrete examples of how this could be used. You say you can think of thousands of examples, but I can only think of one place where I might want to use it (which would be creating a linked page in that can receive events from a parent and pass messages back). Even then, it seems like a nice to have. Maybe I’m not thinking out of the box enough. Could you bullet point a few of your ideas as to where you think this would be useful?
I also can’t imagine what I would use in the Source, Target, Data parameters when calling this from C/AL. Let’s say I want to create a Dimensions Value page that can be called from the General Journal and will update to show those dimension values that are linked to the current line. How would you go about this? Are we suggesting that we have a single instance of Dispatcher in a single instance Codeunit that I access from both objects? Or should I be instantiating a Dispatcher object in my parent and calling a function on the child page passing a reference to the dispatcher?
Once again, thanks for sharing this with the community. All the best, Dave.
Pingback: .NET Tips & Tricks: Mediator Pattern (on steroids) - Navigate Into Success - Microsoft Dynamics NAV - Microsoft Dynamics Community
Pingback: Observer Pattern in Dynamics NAV | geeknikolai
I have tried this and the last example without success for my usecase.
What I am trying to do is when a function is called anywhere from NAV , then a page which is open in foreground should run a function of its own.
Basically this open page should be listening for that function all the time its open.
Currently i have achieved this with Timer which isnt very elegant.