Question

I am creating 10-20 core services in a large application that need to publish various events. I have looked at the IMvxMessenger model and I am trying to ascertain the value in using IMvxMessenger events vs events that are published via our application services.

The main advantage I have with the event being published via one of our services is that developers who use the service can quickly determine what events are available.

e.g. myService.ObserveLogonChange() or myService.LogonChangedEvent etc.

When looking at IMvxMessenger it allows you to publish any class in a very generic way – but knowing how to subscribe to these relies heavily on the developers having a deeper understanding of the code base to know which events to listen too.

So my question is, Is there anything that I lose by having the service publish the event vs the IMvxMessenger approach?

Thanks in advance.

Alan.

Was it helpful?

Solution

Here's a pattern that might work for you.

EDIT: Sample code is located here -> https://github.com/kiliman/MvxEventsSample

Basically, create an inner class in your service class named Events. This will have properties for each event that is published by your service. Then in your view model, you create an instance of this Events class and add whatever handlers you want. This way, you have a nice descriptive class showing what events are available, but still uses MvxMessenger to ensure weak references.

public interface IMyService
{
    void Logon();
    void DoSomething();
}

public class MyService : IMyService
{
    private readonly IMvxMessenger _messenger;

    public MyService(IMvxMessenger messenger)
    {
        _messenger = messenger;
    }

    public void Logon()
    {
        _messenger.Publish(new LogonChangedMessage(this));
    }

    public void DoSomething()
    {
        _messenger.Publish(new AnotherEventMessage(this, string.Format("Do Something at {0}", DateTime.Now)));
    }

    // Events class defines all possible events as properties
    // Notice that we only need setters
    // We also store the subscription tokens
    public class Events
    {
        private readonly IMvxMessenger _messenger;

        public Events(IMvxMessenger messenger)
        {
            _messenger = messenger;
        }

        private MvxSubscriptionToken _logonChangedToken;
        public Action<LogonChangedMessage> OnLogonChanged
        {
            set { _logonChangedToken = _messenger.Subscribe(value); } 
        }

        private MvxSubscriptionToken _anotherEventToken;
        public Action<AnotherEventMessage> OnAnotherEvent
        {
            set { _anotherEventToken = _messenger.Subscribe(value); }
        }
    }

    public class LogonChangedMessage : MvxMessage
    {
        public LogonChangedMessage(object sender) : base(sender)
        {
        }
    }

    public class AnotherEventMessage : MvxMessage
    {
        public AnotherEventMessage(object sender, string text) : base(sender)
        {
            Text = text;
        }

        public string Text { get; set; }
    }
}

And here's how you would use it in the view model. Notice how I create an instance of MyService.Events, and then use lambda expressions to setup the event handlers.

public class FirstViewModel : MvxViewModel
{
    private readonly IMyService _myService;
    private readonly MyService.Events _events;
    private int _counter = 0;

    public FirstViewModel(IMyService myService, IMvxMessenger messenger)
    {
        _myService = myService;

        // Initialize event handlers using lambda expressions
        _events = new MyService.Events(messenger)
        {
            OnLogonChanged = message =>
            {
                Hello = "OnLogonChanged: " + (++_counter);
                Mvx.Trace("OnLogonChanged");
            },
            OnAnotherEvent = message =>
            {
                Hello = message.Text;
                Mvx.Trace("OnAnotherEvent");
            }
        };
    }

    private string _hello;
    public string Hello
    {
        get { return _hello; }
        set { _hello = value; RaisePropertyChanged(() => Hello); }
    }


    private MvxCommand _logonCommand;
    public ICommand LogonCommand
    {
        get
        {
            _logonCommand = _logonCommand ?? new MvxCommand(_myService.Logon);
            return _logonCommand;
        }
    }

    private MvxCommand _doSomethingCommand;
    public ICommand DoSomethingCommand
    {
        get
        {
            _doSomethingCommand = _doSomethingCommand ?? new MvxCommand(_myService.DoSomething);
            return _doSomethingCommand;
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top