Mike Nichols - Son of Nun Technology

Unit of Work and Notification Associated Through Observer

So I am playing around with implementing a way to send messages up from my Domain to my UI without try..catch blocks (exceptions). I am using DTO's that implement a Notification object for communicating messages through the flow of processes. However, this sometimes requires copying message from one objet to another and it seems to be a hack to do so. This is due to the return of only one object from methods, assuming I am not going to implement out parameters on all my methods and I don't want to always throw exceptions for messaging purposes. I think bad user data is expected so these kind of occurences don't warrant an exception...But how to create a consistent way of sending messages up from my Domain layer up to my UI without exceptions or hacks?

I got to thinking that I since I am implementing the Unit of Work pattern, why not simply have an association with some kind of Notification Manager take care of gathering and delivering all these messages?  I am using an implementation of IUnitOfWork from Ayende's Rhino Commons . A static UnitOfWork class manages the Current Unit of Work and this is what I want to attach my Notification to. So let's see what happens.

To begin, I am sending notifications through an object that implements my INotification interface:

    public interface INotification

    {

        IList<INotificationItem> Items { get;}

        bool HasItems { get;}

        bool HasErrors { get;}

        void AddItem(INotificationItem item);

        void Clear();

        IEnumerable<INotificationItem> GetBySeverity(params NotificationSeverity[] severity);

 

    }

 

 For my web app, I have an INotificationHandler that simply parses each INotification implementation and writes the messages to a standard Message control from my presenter. I won't show that code here. Just suffice to say that the PresenterBase from which my Presenters derive contains a reference to an INotificationHandler implementation and it writes to the web page.

IUnitOfWork looks like this after I added an event called UnitOfWorkFlushed like so:

        void Flush();

 

        ITransaction BeginTransaction();

        ITransaction BeginTransaction(IsolationLevel isolationLevel);

 

        event EventHandler UnitOfWorkFlushed;

 When I want to end my Unit of Work, this event will get fired.

Now I am going to implement the Observer pattern to hook into my Unit of Work so first my INotificationObserver interface:

    public interface INotificationObserver

    {

        void Notify(params INotification[] notifications );

    }

My Presenters will all implement this INotificationObserver interface so that when the UnitOfWork is flushed the Presenter can handle how any notifications are shown to the user. But I need to register the observer WITH something.

Now, I don't want to mix my Unit of WOrk responsibilities with Notification responsibilities...that smells to me. The event I implemented avoids that kind of commingling of responsibilities. What I want is  to have a way to access my NotificationManager from everywhere in my app, so I implement a (Singleton) Notification manager that has a dictionary of IUnitOfWork mapped to my INotificationObservers:

    public class NotificationManager

    {

        #region Singleton Instantiation

        NotificationManager() { }

        public static NotificationManager Instance

        {

            get{ return Singleton.instance; }

        }

        class Singleton

        {

            static Singleton() { }

            internal static readonly NotificationManager instance =

                new NotificationManager();

        }

        #endregion

 

        private IDictionary<IUnitOfWork, INotificationObserver> _hash =

            new Dictionary<IUnitOfWork, INotificationObserver>();

 

        private IDictionary<IUnitOfWork, List<INotification>> _notifications =

            new Dictionary<IUnitOfWork, List<INotification>>();

 

        public void RegisterHandler(IUnitOfWork unitOfWork,INotificationObserver observer )

        {

            lock (_hash)

            {

                _hash.Add(unitOfWork, observer);

            }

            unitOfWork.UnitOfWorkFlushed += new EventHandler(Notify);

        }

        private void Notify(object sender, EventArgs e)

        {

            IUnitOfWork unitOfWork = (IUnitOfWork)sender;

            INotificationObserver observer = _hash[unitOfWork];

            observer.Notify(_notifications[unitOfWork].ToArray());

 

        }

        public void AddNotification(INotification notification)

        {

            _notifications[UnitOfWork.Current].Add(notification);

        }

        public void AddItem(INotificationItem notificationItem)

        {

            if(_notifications[UnitOfWork.Current].Count==0)

                _notifications[UnitOfWork.Current].Add(new Notification());

 

            _notifications[UnitOfWork.Current][0].AddItem(notificationItem);

        }

 

    }

Within the constructor of my PresenterBase, I can register it along with the UnitOfWork.Current with the NotificationManager and then any INotificationItem messages I need to add throughout the course of a Unit of Work will be added to the appropriate Notification.

            NotificationManager.Instance.RegisterHandler(UnitOfWork.Current, this);

Notice in the RegisterHandler method in the NotificationManager that I wire up the IUnitOfWork.UnitOfWorkFlushed event to its Notify method. The Notify method simply grabs the appropriate INotificationObserver implementation and calls its Notify method, passing in all the Notifications that were gathered during the course of the Unit of Work. Though not shown, the clean up of these NOtifications should be done at this time as well. My PresenterBase simply iterates all these INotifications and parses them to the view:

        public void Notify(params INotification[] notifications)

        {

            foreach(INotification notification in notifications)

            {

                NotificationHandler.Parse(_view, notification);

            }

        }

What is nice is my INotificationObserver doesn't have to be some kind of View helper...I could pass in a logger as an INotificationObserver as well and let it write messages to a text file in its own Notify() implementation.

 

I just drummed this up last night, but can anyone see any fatal flaws in my design here? It almost seems to simple yet I can't think of why it would break.Comments would be appreciated!