New Mediator

420 views
Skip to first unread message

Marlon Grech

unread,
Apr 6, 2009, 3:56:14 PM4/6/09
to wpf-di...@googlegroups.com
Hi all,

Today I had a few minutes to think about the "Memory Leak" in the Mediator implementation I did. I implemented a new version that solves this issue. I am not 100% happy since my solution uses Reflection (yes I love reflection and end up fitting it everywhere).

Basically the memory leak is solved by using a WeakReference and then using reflection to call a method on the WeakRefernce Target. This way GC can collect the ViewModel when it is not being used any more and the Mediator can check if the ViewModel is alive or not (and if not remove it from the InvocationList)

here is the WeakDelegate (Josh suggested this name I was gonna go for something crazy such as WeakCollogueInvoker :) lol haha)

class WeakDelegate : WeakReference
        {
            public string Method { get; private set; }

            private MethodInfo methodInfo;

            public WeakDelegate(object target, string method)
                : base(target)
            {
                Method = method;
                methodInfo = Target.GetType().GetMethod(Method, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
                if (methodInfo == null)
                    throw new InvalidOperationException(String.Format("Method {0} was not found on target object", Method));
            }

            public void Notify(object args)
            {
                if (IsAlive)
                    methodInfo.Invoke(Target, new[] { args });
            }
        }

... and here is how the Mediator does the invocation / cleanup

if (invocationList.ContainsKey(message))
            {
                for (int i = 0; i < invocationList[message].Count; i++)
                {
                    var weakDelegate = invocationList[message][i];
                    if (weakDelegate.IsAlive)
                        weakDelegate.Notify(args);
                    else//remove the weak delegate from the invokation list
                    {
                        invocationList[message].RemoveAt(i);
                        i--;
                    }
                }
            }

... in Order to Register for a message from a VM you do the following

Mediator.Instance.Register(MediatorMessages.Message1, this, "Test");

anyway I attached a project that demos this... have a look and tell me what you think..... once we agree on this I will publish this as an update to my article....

P.S I am using strings not an enum. I do this becuase strings can be defined in other projects then the Mediator project.... I see a Mediator as a chat room.... A chat room does not know what messages are passing... the people chatting define those.... Mediator for me is similar


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/

Marlon Grech

unread,
Apr 6, 2009, 3:58:06 PM4/6/09
to wpf-di...@googlegroups.com
oops... forgot to attach the file :D

hihi :D


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



MediatorTest.zip.rename2

Josh Smith

unread,
Apr 6, 2009, 3:59:44 PM4/6/09
to wpf-di...@googlegroups.com
I don't think you should include the 'Static' binding flag.  The callbacks will always be instance methods on the Target object, no?

Marlon Grech

unread,
Apr 6, 2009, 4:00:29 PM4/6/09
to wpf-di...@googlegroups.com
and yes I know this would blow up in a PartialTrust CAS.....


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



On Mon, Apr 6, 2009 at 9:56 PM, Marlon Grech <marlo...@gmail.com> wrote:

Marlon Grech

unread,
Apr 6, 2009, 4:01:49 PM4/6/09
to wpf-di...@googlegroups.com
I did that jsut in case someone wants to define a method like this

public static void Test(object test)
        {
            MessageBox.Show("Message from mediator");
        }

otherwise reflection would not get that method...


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Josh Smith

unread,
Apr 6, 2009, 4:35:35 PM4/6/09
to wpf-di...@googlegroups.com
I think it would be better to decorate the callback methods of the Colleagues with an attribute, and specify the message ID in the attribute's constructor.  In your Mediator/WeakDelegate code, scan the Target object (i.e. Colleague) for a method decorated with your custom attribute, where the MessageID equals the message of interest.  This is better than passing in the method name to the Mediator for the following reasons:

1) The method names on the Colleagues classes are not duplicated in the code.  If you change the name of the callback, you don't have to remember to change the method name passed to the Mediator.

2) The Colleague class's are more self-documenting, because the callback methods are attributed with the Message ID that they are associated with.

3) The callback locating logic is simplified, because you don't have to worry about things like method overloads.

What do you think?

Josh

Marlon Grech

unread,
Apr 6, 2009, 4:45:47 PM4/6/09
to wpf-di...@googlegroups.com
I like this....

I would do it a bit different.... (or the same as you are saying which would mean I didn't understand correctly, which is most likely the case here :) )


something like this


class MyVM
{
    [MediatorNotification(MediatorMessages.Message1]
    public void Test(object args )
    {
       ....
    }
   
    public MyVM()
   {
              Mediator.Register(this);
   }
}

the register would scan the VM and register all the methods to the messages. This way you only scan once.... what do you think? I think we are saying the same thing



Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Mike Brown

unread,
Apr 6, 2009, 4:49:13 PM4/6/09
to wpf-di...@googlegroups.com
I think that's a brilliant idea Josh...however, how would the registration occur? Another alternative would be to use that static reflection trick that I posted for INPC

Mike Brown

unread,
Apr 6, 2009, 4:50:29 PM4/6/09
to wpf-di...@googlegroups.com
Remember you can't use a parameter to an Attribute unless it's a compile time constant or an enum.

Josh Smith

unread,
Apr 6, 2009, 4:50:54 PM4/6/09
to wpf-di...@googlegroups.com
I'm not sure.  I might want to register/unregister for certain messages at certain times. Then again, I could put logic into my callbacks that aborts if i don't want to act on some message at the time.  Hmm...

Josh Smith

unread,
Apr 6, 2009, 4:51:47 PM4/6/09
to wpf-di...@googlegroups.com
In Marlon's setup, the message IDs can be const strings exposed off some class.  That should work ok.

Marlon Grech

unread,
Apr 6, 2009, 4:53:59 PM4/6/09
to wpf-di...@googlegroups.com
hehe... I already have the code in my mind.... all I need is 5 minutes to write it :P haha....

but let's wait for the other Disciples to put their input....

P.S And yes mike it is do able.... I already did this in a sample app with a similar setup.... in the example I wrote the parameter is a constant which is the way you should define a Mediator message.


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Marlon Grech

unread,
Apr 6, 2009, 5:16:28 PM4/6/09
to wpf-di...@googlegroups.com
couldn't help it... otherwise would not sleep...

here is the new Register method

public void Register(object target)
        {
            foreach (var methodInfo in target.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
                foreach (RegisterMediatorMessageAttribute attribute in methodInfo.GetCustomAttributes(typeof(RegisterMediatorMessageAttribute), true))
                    invocationList.AddValue(attribute.Message, new WeakDelegate(target, methodInfo.Name));
        }

... The Attribute

[AttributeUsage(AttributeTargets.Method)]
    public class RegisterMediatorMessageAttribute : Attribute
    {
        public string Message { get; set; }

        public RegisterMediatorMessageAttribute(string message)
        {
            Message = message;
        }
    }

... and now the cool part

How the VM uses this
class ColleagueA {
        public ColleagueA()
        {
            Mediator.Instance.Register(this);
        }

        [RegisterMediatorMessage(MediatorMessages.Message1)]

        public static void Test(object test)
        {
            MessageBox.Show("Message from mediator");
        }

What do you think guys?

P.S in a real world application this  Mediator.Instance.Register(this); will not be in every VM because it would be in the BaseViewModel (or at least i would put it there so that you don't have to call it every time)


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Mike Brown

unread,
Apr 6, 2009, 5:28:52 PM4/6/09
to wpf-di...@googlegroups.com
I wonder if that would scale out to where the Mediator would be some kind of service on another machine. That would work well in that scenario Udi Dahan talked about in this month's MSDN.

Marlon Grech

unread,
Apr 6, 2009, 5:32:19 PM4/6/09
to wpf-di...@googlegroups.com
Why would you want the Mediator as a service on another machine? I don't think this needs that kind of scalability


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Mike Brown

unread,
Apr 6, 2009, 6:42:54 PM4/6/09
to wpf-di...@googlegroups.com
Look at the article I linked to. That's a perfect example of how a distributed mediator would be a good thing.

Josh Smith

unread,
Apr 7, 2009, 12:17:32 AM4/7/09
to wpf-di...@googlegroups.com
Hey all,

I set aside some time tonight to work on the Mediator problem.  I refined Marlon's awesome solution, and removed the need for using reflection to locate the target method.  I posted an entry on my blog, showing the prototype, and asked for suggestions/improvements/bugs/etc.  If I get any good feedback on it, I'll send them your way.

Here's the blog post:

http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/

Josh

Sacha Barber

unread,
Apr 7, 2009, 3:41:27 AM4/7/09
to wpf-di...@googlegroups.com
Marlon

I like Joshes idea of attributes, let us know when we have some new code to look at.


Date: Mon, 6 Apr 2009 18:42:54 -0400
Subject: [WPF Disciples] Re: New Mediator
From: mbro...@gmail.com
To: wpf-di...@googlegroups.com

Get the New Internet Explore 8 Optimised for MSN. Download Now

Marlon Grech

unread,
Apr 7, 2009, 3:44:56 AM4/7/09
to wpf-di...@googlegroups.com
I posted the code yesterday.... here let me attach it again

here is the new Register method

public void Register(object target)
        {
            foreach (var methodInfo in target.GetType().GetMethods(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
                foreach (RegisterMediatorMessageAttribute attribute in methodInfo.GetCustomAttributes(typeof(RegisterMediatorMessageAttribute), true))
                    invocationList.AddValue(attribute.Message, new WeakDelegate(target, methodInfo.Name));
        }

... The Attribute

[AttributeUsage(AttributeTargets.Method)]
    public class RegisterMediatorMessageAttribute : Attribute
    {
        public string Message { get; set; }

        public RegisterMediatorMessageAttribute(string message)
        {
            Message = message;
        }
    }

... and now the cool part

How the VM uses this
class ColleagueA {
        public ColleagueA()
        {
            Mediator.Instance.Register(this);
        }

        [RegisterMediatorMessage(MediatorMessages.Message1)]

        public static void Test(object test)
        {
            MessageBox.Show("Message from mediator");
        }


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



MediatorTest.zip.rename2

Marlon Grech

unread,
Apr 7, 2009, 3:46:16 AM4/7/09
to wpf-di...@googlegroups.com
Josh,

Maybe I am missing something but your solution still would blow up in Partial trust... Delegate.CreateDelegate is still reflection at the end of the day no? (It still has CAS for ReflectionPermission)


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Laurent Bugnion, GalaSoft [MVP, MCP]

unread,
Apr 7, 2009, 5:05:26 AM4/7/09
to wpf-di...@googlegroups.com

Hey Josh,

 

I just commented on your blog with 2 questions. Would love if you can reply there. In the mean time I will try that myself, thanks!!

 

Laurent

 

From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Josh Smith
Sent: Tuesday, April 07, 2009 6:18 AM
To: wpf-di...@googlegroups.com
Subject: [WPF Disciples] Re: New Mediator

 

Hey all,

No virus found in this incoming message.
Checked by AVG - www.avg.com
Version: 8.0.238 / Virus Database: 270.11.43/2043 - Release Date: 04/06/09 06:22:00

Laurent Bugnion, GalaSoft [MVP, MCP]

unread,
Apr 7, 2009, 5:31:49 AM4/7/09
to wpf-di...@googlegroups.com

Just curious, did any of you guys try NInject or another Dependency Injection framework to solve this kind of issues? I know I promised I would write about it, and didn’t have time yet, but with NInject you get a central repository of objects, which provides an easy access to them. For example, if you create a MainViewModel and a SecondaryViewModel using NInject, you can then easily get the SecondaryViewModel from the MainViewModel and call methods on it directly.

 

NInject adds a little overhead to the application (especially in Silverlight where size matters), but offers the advantage of a well known, well tested framework to solve this kind of issues. In addition, it is very easy to create a design time view model vs a runtime view model, and to keep the design time implementation separate.

 

Just curious to hear your thoughts, and yes I will write about it, I promise J

 

Laurent

Version: 8.0.238 / Virus Database: 270.11.43/2043 - Release Date: 04/06/09 18:59:00

Shawn Wildermuth

unread,
Apr 7, 2009, 5:49:08 AM4/7/09
to wpf-di...@googlegroups.com

I am currently writing a MSDN article on Prism (which uses Unity’s DI container, but you could use Ninject or other container) and it solves this issue with a typical IoC model but also for Silverlight allows you to specify modules in .xap files that can be downloaded behind the scenes or on demand.  Prism encompasses other problems (I like the DelegateCommand<> and EventAggregator a lot too). In this way I think Prism solves a lot of problems for WPF, but the ondemand and componentization at the .xap level loading of silverlight projects make it a home run for Silverlight IMHO.

 

Thanks,

 

Shawn Wildermuth

http://wildermuth.com

https://agilitrain.com

Microsoft MVP (C#), MCSD.NET, Author and Speaker

 

The Silverlight Tour is coming to a city near you!

Laurent Bugnion, GalaSoft [MVP, MCP]

unread,
Apr 7, 2009, 6:20:35 AM4/7/09
to wpf-di...@googlegroups.com
Yes the solution I experimented with NInject worked like a charm for
Silverlight too.

-----Original Message-----
From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com]
On Behalf Of Shawn Wildermuth
Sent: Tuesday, April 07, 2009 11:49 AM
To: wpf-di...@googlegroups.com
Subject: [WPF Disciples] Re: New Mediator

I am currently writing a MSDN article on Prism (which uses Unity's DI
container, but you could use Ninject or other container) and it solves
this issue with a typical IoC model but also for Silverlight allows you
to specify modules in .xap files that can be downloaded behind the
scenes or on demand. Prism encompasses other problems (I like the
DelegateCommand<> and EventAggregator a lot too). In this way I think
Prism solves a lot of problems for WPF, but the ondemand and
componentization at the .xap level loading of silverlight projects make
it a home run for Silverlight IMHO.

Thanks,

Shawn Wildermuth

http://wildermuth.com <http://wildermuth.com/>

https://agilitrain.com <http://wildermuthconsulting.com/>

Microsoft MVP (C#), MCSD.NET, Author and Speaker

The Silverlight Tour <http://www.silverlight-tour.com/> is coming to a

Josh Smith

unread,
Apr 7, 2009, 8:11:05 AM4/7/09
to wpf-di...@googlegroups.com
Yeah, that's true, but it doesn't use MethodInfo.Invoke(), which is supposed to be slower than CreateDelegate + invoking a delegate (according to the info I saw on the Web, which isn't necessarily correct!).  I'm not too worried about the permissions thing, but the performance is something worth considering. 

Josh

Marlon Grech

unread,
Apr 7, 2009, 8:22:40 AM4/7/09
to wpf-di...@googlegroups.com
ow ok.... fair enough.... CreateDelegate is in fact better performance wise...

Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Josh Smith

unread,
Apr 7, 2009, 8:25:14 AM4/7/09
to wpf-di...@googlegroups.com
I'm still not convinced that I'm happy with this Mediator design.  The prototype I posted last night works, but I still think that the attribute-based design we'd discussed yesterday might be better.  Perhaps it might be good to allow for both message-by-message registration, and also wholesale registration for all of an object's message sinks.  What do you think?  What would you prefer?

Josh

Marlon Grech

unread,
Apr 7, 2009, 8:33:10 AM4/7/09
to wpf-di...@googlegroups.com
Yesterday I posted the code for the attributes... I think it cool... did you have time to look at it?

Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Sacha Barber

unread,
Apr 7, 2009, 8:35:35 AM4/7/09
to wpf-di...@googlegroups.com
I liked it.




Date: Tue, 7 Apr 2009 14:33:10 +0200

Subject: [WPF Disciples] Re: New Mediator

" Upgrade to Internet Explorer 8 Optimised for MSN. " Download Now

Josh Smith

unread,
Apr 7, 2009, 8:40:53 AM4/7/09
to wpf-di...@googlegroups.com
I saw it, and loved it!  Perhaps you might want to roll my WeakAction implementation (which is faster than the MethodInfo.Invoked() approach) into your attribute-based approach? 

Josh

Marlon Grech

unread,
Apr 7, 2009, 8:41:52 AM4/7/09
to wpf-di...@googlegroups.com
yea definitly :)

Cool will stitch the code together and publish it :D


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Josh Smith

unread,
Apr 7, 2009, 8:43:40 AM4/7/09
to wpf-di...@googlegroups.com
As Karl/KDAWG/Keith mentioned to me yesterday, this is the real power of the Disciples.  The fact that passionate people all over the world can easily collaborate on projects like this is fantastic.  :)

Josh

Marlon Grech

unread,
Apr 7, 2009, 8:50:57 AM4/7/09
to wpf-di...@googlegroups.com
The Disciples ROCK :) yea yea :D


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Sacha Barber

unread,
Apr 7, 2009, 8:50:09 AM4/7/09
to wpf-di...@googlegroups.com
Yes I see bit from all of us in there.

GREAT


Date: Tue, 7 Apr 2009 08:43:40 -0400

Subject: [WPF Disciples] Re: New Mediator

Bill Kempf

unread,
Apr 7, 2009, 9:27:15 AM4/7/09
to wpf-di...@googlegroups.com
Marlon,
 
I've finally gotten the chance to look at your Mediator blog post.  I was correct... this is an alternate implementation of the EventAggregator in Prism.  Have you looked at it?  There's always benefit in implementing things yourself.  At worst, you have a learning experience.  At best, you come up with a better solution.  However, it's also useful in those situations to look closely at existing solutions for inspiration.  Especially quality implementations, like Prism has.

--
Quidquid latine dictum sit, altum sonatur.
- Whatever is said in Latin sounds profound.

War is peace. Freedom is slavery.  Bugs are features.

Laurent Bugnion, GalaSoft [MVP, MCP]

unread,
Apr 7, 2009, 9:43:10 AM4/7/09
to wpf-di...@googlegroups.com

Hey guys,

 

I don’t really prefer attribute-based approaches in general, I guess this is my alt.net hidden side speaking LOL. I am currently experimenting with a combination if interface/implementation based messages, and the WeakReference approach that Josh describes. Maybe it can provide an alternative.

 

Cheers,

Laurent

 

From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Sacha Barber
Sent: Tuesday, April 07, 2009 2:50 PM
To: wpf-di...@googlegroups.com
Subject: [WPF Disciples] Re: New Mediator

 

Yes I see bit from all of us in there.

GREAT


Date: Tue, 7 Apr 2009 08:43:40 -0400
Subject: [WPF Disciples] Re: New Mediator
From: flappl...@gmail.com
To: wpf-di...@googlegroups.com

As Karl/KDAWG/Keith mentioned to me yesterday, this is the real power of the Disciples.  The fact that passionate people all over the world can easily collaborate on projects like this is fantastic..  :)

Josh

No virus found in this incoming message.


Checked by AVG - www.avg.com

Version: 8.0.238 / Virus Database: 270.11.44/2044 - Release Date: 04/06/09 18:59:00

Mike Brown

unread,
Apr 7, 2009, 9:44:01 AM4/7/09
to wpf-di...@googlegroups.com
I've been looking at AOP IL weaving frameworks lately. First there's PostSharp. Using postsharp attributes, you can create weave code into your application that wires your VMs to your mediator at compile time. That let's you avoid the performance hits and security limitations of reflection.

Josh Smith

unread,
Apr 7, 2009, 9:48:09 AM4/7/09
to wpf-di...@googlegroups.com
The more implementations to compare, the better.  I am hoping that every Disciple who is interested in this will blog their Mediator implementation, and then we can compare them all to come up with the optimal design.  And, as Bill pointed out, we should also compare ours to the EventAggregator in Prism/CAL.

Josh

Josh Smith

unread,
Apr 7, 2009, 9:49:17 AM4/7/09
to wpf-di...@googlegroups.com
That sounds wickedly cool!  Does doing this "IL weaving" result in code that is difficult to debug in Visual Studio?

Marlon Grech

unread,
Apr 7, 2009, 10:02:57 AM4/7/09
to wpf-di...@googlegroups.com
There is 1 big flaw in using PostSharp for this Mike (I used postsharp in Jasema). You must install postSharp to compile the code, if you don't have it installed nothing gets generated and nothing works. I don't think that having to install PostSharp in order to use the Mediator would be a good idea... I think postSharp is great for building apps but not for use in a library



Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Mike Brown

unread,
Apr 7, 2009, 10:10:49 AM4/7/09
to wpf-di...@googlegroups.com
You can wrap it all up into a project template or use VSI. I think that's one thing that many developers fail to take advantage of is creating custom project/item templates for VS. I think I've only done it once myself.

Marlon Grech

unread,
Apr 7, 2009, 10:13:21 AM4/7/09
to wpf-di...@googlegroups.com
cool... you should blog on this because I had no idea you can do that...


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Mike Brown

unread,
Apr 7, 2009, 10:13:32 AM4/7/09
to wpf-di...@googlegroups.com
I think it does end up generating some "magic code" that is difficult to step into. I haven't really dug deeply into it myself beyond reading some of the introductory documentation. Also I can't imagine it'd be incredibly easy to unit test/mock out the implementations. I think I'll do a spike on a PostSharp driven mediator and report my results.

Josh Smith

unread,
Apr 7, 2009, 10:14:44 AM4/7/09
to wpf-di...@googlegroups.com
Looking forward to reading your results, Mike.  This sounds very interesting.

Karl Shifflett

unread,
Apr 7, 2009, 10:32:33 AM4/7/09
to wpf-di...@googlegroups.com

Sorry I couldn’t get into this yesterday.

 

I’ll get my head around this tonight and see where I land.

 

Marlon great point about partial trust.

 

This is solvable.

 

kdawg

Josh Smith

unread,
Apr 7, 2009, 11:17:09 AM4/7/09
to wpf-di...@googlegroups.com
I just discovered a minor improvement that can be made to my WeakAction class.  Instead of storing the MethodInfo exposed by the Action<object>'s Method property, we can just store the method name:

internal class WeakAction : WeakReference
{
    readonly string _methodName;

    internal WeakAction(Action<object> action)
        : base(action.Target)
    {
        _methodName = action.Method.Name;
    }

    internal Action<object> CreateAction()
    {
        if (!base.IsAlive)
            return null;

        try
        {
            // Rehydrate into a real Action
            // object, so that the method
            // can be invoked on the target.

            return Delegate.CreateDelegate(
                typeof(Action<object>),
                base.Target,
                _methodName)
                as Action<object>;
        }
        catch
        {
            return null;
        }
    }
}

Another point of discussion that we have yet to touch on is thread affinity and thread safety.  In my implementation, Mediator derives from DependenyObject.  This allows me to ensure that all messages are broadcast on the UI thread.  This allows for the NotifyColleagues method to be implemented like this:

public void NotifyColleagues(object message, object parameter)
{
    if (base.CheckAccess())
    {
        List<Action<object>> actions =
            _messageToCallbacksMap.GetActions(message);

        if (actions != null)
            actions.ForEach(action => action(parameter));
    }
    else
    {
        base.Dispatcher.BeginInvoke((Action)delegate
        {
            this.NotifyColleagues(message, parameter);
        },
        DispatcherPriority.Send);
    }
}

I'm not sure if this is a good idea or not.  I assume that if this is being used in WPF apps (possibly SL apps too) then you'd want your ViewModels to be notified of messages on the UI thread, but am not convinced that this will always be the case.  Also, if we are going to support sending out notifications from worker threads, the Mediator and associated types should take thread safety into account.  What are your thoughts on this?

Josh

Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



On Mon, Apr 6, 2009 at 10:53 PM, Marlon Grech <marlo...@gmail.com> wrote:
hehe... I already have the code in my mind.... all I need is 5 minutes to write it :P haha....

but let's wait for the other Disciples to put their input....

P.S And yes mike it is do able.... I already did this in a sample app with a similar setup.... in the example I wrote the parameter is a constant which is the way you should define a Mediator message.
Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



On Mon, Apr 6, 2009 at 10:51 PM, Josh Smith <flappl...@gmail.com> wrote:
In Marlon's setup, the message IDs can be const strings exposed off some class.  That should work ok.
On Mon, Apr 6, 2009 at 4:50 PM, Mike Brown <mbro...@gmail.com> wrote:
Remember you can't use a parameter to an Attribute unless it's a compile time constant or an enum.
On Mon, Apr 6, 2009 at 4:45 PM, Marlon Grech <marlo...@gmail.com> wrote:
I like this....

I would do it a bit different.... (or the same as you are saying which would mean I didn't understand correctly, which is most likely the case here :) )


something like this


class MyVM
{
    [MediatorNotification(MediatorMessages.Message1]
    public void Test(object args )
    {
       ....
    }
   
    public MyVM()
   {
              Mediator.Register(this);
   }
}

the register would scan the VM and register all the methods to the messages. This way you only scan once.... what do you think? I think we are saying the same thing
Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



On Mon, Apr 6, 2009 at 10:35 PM, Josh Smith <flappl...@gmail.com> wrote:
I think it would be better to decorate the callback methods of the Colleagues with an attribute, and specify the message ID in the attribute's constructor.  In your Mediator/WeakDelegate code, scan the Target object (i.e. Colleague) for a method decorated with your custom attribute, where the MessageID equals the message of interest.  This is better than passing in the method name to the Mediator for the following reasons:

1) The method names on the Colleagues classes are not duplicated in the code.  If you change the name of the callback, you don't have to remember to change the method name passed to the Mediator.

2) The Colleague class's are more self-documenting, because the callback methods are attributed with the Message ID that they are associated with.

3) The callback locating logic is simplified, because you don't have to worry about things like method overloads.

What do you think?

Josh

Marlon Grech

unread,
Apr 7, 2009, 11:24:16 AM4/7/09
to wpf-di...@googlegroups.com
I think this should be a opt in opt out...

Basically the idea is, initialize the Mediator yourself (so no more singleton, that way as you Josh suggested you can have x number of Mediators) and pass the Dispatcher... If you don't then you have to ensure Thread affinity...  What do you think?


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Josh Smith

unread,
Apr 7, 2009, 11:27:34 AM4/7/09
to wpf-di...@googlegroups.com
That sounds reasonable, Marlon.  I think that's the way to go.  Now, what about thread safety?  I think we'll need to identify areas in the Mediator related classes that need to be thread-safe.  Probably anything that touches the internal storage container (in my prototype, the MessageToActionsMap class).

Marlon Grech

unread,
Apr 7, 2009, 11:37:46 AM4/7/09
to wpf-di...@googlegroups.com
yep we definitely need a lock in there.... should be quite easy no rocket science...

I will post the code to the group in 1 hour :)
then review and when we are happy we publish it.... Maybe you know what we should publish it via our blog :)

what do you think!


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Laurent Bugnion, GalaSoft [MVP, MCP]

unread,
Apr 7, 2009, 11:37:11 AM4/7/09
to wpf-di...@googlegroups.com

I got one implementation working, need to refine it, then I will blog about it. It is based on the following concepts:

 

IMessage<T>: this is an interface that defines the message to be broadcasted. It has one property of type T named Content

 

IMessageRecipient: This is the interface that all message recipients must implement. In a WPF application, the ViewModels will typically be IMessageRecipients. One method void ReceiveMessage<T>(IMessage<T> message);

 

Messenger: This is the mediator. It keeps a list of WeakReferences on IMessageRecipients. It has a method Register(IMessageRecipient recipient, Type messageType) for registration, and a method Broadcast<U, T>(U message) where U : IMessage<T> for broadcast

 

Then there is a list of messages, for example public class EditMessage : IMessage<CustomerViewModel>

 

This Edit message tells a VM that it should now set its DataContext to the Content (of type CustomerViewModel). In a typical LOB application, I have SaveMessage, EditMessage, LoadMessage, and we can even define a GenericMessage that looks like public class GenericMessage : IMessage<object>

 

I can easily unit test my mediator. The last thing which I am still not too happy about is the best way for the IMessageRecipient to get a reference on the mediator. For the moment I store one instance in the App resources, I could of course also use a Singleton. What is your suggestion?

 

Cheers,

Laurent

 

From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Josh Smith
Sent: Tuesday, April 07, 2009 3:48 PM
To: wpf-di...@googlegroups.com
Subject: [WPF Disciples] Re: New Mediator

 

The more implementations to compare, the better.  I am hoping that every Disciple who is interested in this will blog their Mediator implementation, and then we can compare them all to come up with the optimal design.  And, as Bill pointed out, we should also compare ours to the EventAggregator in Prism/CAL.

Josh

Josh Smith

unread,
Apr 7, 2009, 11:41:07 AM4/7/09
to wpf-di...@googlegroups.com
We'll need to be very careful about where we use locks, though, because they are notoriously slow. 

Marlon Grech

unread,
Apr 7, 2009, 11:43:23 AM4/7/09
to wpf-di...@googlegroups.com
Well we can do a ReaderWriterSlim but I don't really see the need.... At the end of the day it's not that there will be so much chatting going on.... I think normal locks should be fine really... What do you think?


Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Josh Smith

unread,
Apr 7, 2009, 11:43:43 AM4/7/09
to wpf-di...@googlegroups.com
Laurent - I think that a class as reusable as this, should be flexible enough to be used either as a Singleton, or just as a local variable created when initializing some colleague objects.  In my demo app, I injected the Mediator instance into the data objects, which then store a reference to it:

public DemoWindow()
{
    InitializeComponent();

    Mediator mediator = new Mediator();
    this.stackPanelA.DataContext = new ObjectA(mediator);
    this.stackPanelB.DataContext = new ObjectB(mediator);
}

This might be overly simplistic for many apps, but it's viable in some situations.

Josh

Josh Smith

unread,
Apr 7, 2009, 11:45:26 AM4/7/09
to wpf-di...@googlegroups.com
We can start with that, and if it becomes a problem, optimize later.  :)

Laurent Bugnion, GalaSoft [MVP, MCP]

unread,
Apr 7, 2009, 12:03:30 PM4/7/09
to wpf-di...@googlegroups.com

Yep, good thinking. Using the App store or a Singleton works fine too. I am implementing a LOB example based on my WCF service I demoed at MIX. It works really well so far.

No virus found in this incoming message..


Checked by AVG - www.avg.com

Version: 8.0.238 / Virus Database: 270.11.44/2044 - Release Date: 04/06/09 18:59:00

 

No virus found in this incoming message.
Checked by AVG - www.avg.com
Version: 8.0.238 / Virus Database: 270.11.44/2044 - Release Date: 04/06/09 18:59:00

Josh Smith

unread,
Apr 7, 2009, 2:14:03 PM4/7/09
to wpf-di...@googlegroups.com
I just checked out EventAggregator, and must agree, that it is quite awesome.  I think we're wasting time working on a new Mediator implementation, before looking at EA.  It already does what we're doing, even has a WeakAction equivalent known as DelegateReference.  I can see the need perhaps for a lighter version, like how my RelayCommand is a lighter version of DelegateCommand in Prism. 

Josh

On Tue, Apr 7, 2009 at 9:27 AM, Bill Kempf <wek...@gmail.com> wrote:

Mike Brown

unread,
Apr 7, 2009, 2:16:03 PM4/7/09
to wpf-di...@googlegroups.com
No ReaderWriterSlim in SL...no ReaderWriterLock either for that matter.

Pavan Podila

unread,
Apr 7, 2009, 3:16:29 PM4/7/09