public void Add(object referenceObject, string path,
                        Delegates.FileChangedHandlerDelegate fileChanged,
                        Delegates.FileCreatedHandlerDelegate fileCreated,
                        Delegates.FileDeletedHandlerDelegate fileDeleted,
                        Delegates.FileRenamedHandlerDelegate fileRenamed)
        {
            string folder = GetFolder(path);

            FolderMonitor folderMonitor = null;

            if (_FolderMonitors.ContainsKey(folder))
            {
                if (!_FolderMonitors[folder].ReferencedObjects.Exists(x => x.Equals(referenceObject)))
                {
                    folderMonitor = _FolderMonitors[folder];
                }
                else
                {
                    return;
                }
            }
            else
            {
                folderMonitor = new FolderMonitor(folder);

                if (!_FolderMonitors.TryAdd(folder, folderMonitor))
                {
                    throw new Exception(string.Format("failed to add folder '{0}' monitor.", folder));
                }
            }

            folderMonitor.ReferencedObjects = folderMonitor.ReferencedObjects.Append(referenceObject);

            if (fileChanged != null)
            {
                folderMonitor.FileChanged += fileChanged;
            }
            if (fileCreated != null)
            {
                folderMonitor.FileCreated += fileCreated;
            }
            if (fileDeleted != null)
            {
                folderMonitor.FileDeleted += fileDeleted;
            }
            if (fileRenamed != null)
            {
                folderMonitor.FileRenamed += fileRenamed;
            }

            folderMonitor.Start();
        }
        public void Remove(object referenceObject, string path,
                           Delegates.FileChangedHandlerDelegate fileChanged,
                           Delegates.FileCreatedHandlerDelegate fileCreated,
                           Delegates.FileDeletedHandlerDelegate fileDeleted,
                           Delegates.FileRenamedHandlerDelegate fileRenamed)
        {
            string folder = GetFolder(path);

            FolderMonitor folderMonitor = null;

            if (_FolderMonitors.ContainsKey(folder) && _FolderMonitors[folder].ReferencedObjects.Exists(x => x.Equals(referenceObject)))
            {
                folderMonitor = _FolderMonitors[folder];
            }
            else
            {
                return;
            }

            folderMonitor.ReferencedObjects = folderMonitor.ReferencedObjects.Remove(x => x.Equals(referenceObject));

            if (fileChanged != null)
            {
                folderMonitor.FileChanged -= fileChanged;
            }
            if (fileCreated != null)
            {
                folderMonitor.FileCreated -= fileCreated;
            }
            if (fileDeleted != null)
            {
                folderMonitor.FileDeleted -= fileDeleted;
            }
            if (fileRenamed != null)
            {
                folderMonitor.FileRenamed -= fileRenamed;
            }

            if (folderMonitor.ReferencedObjects.Length == 0)
            {
                folderMonitor.Stop();
                if (!_FolderMonitors.TryRemove(folder, out folderMonitor))
                {
                    // TODO: throw
                }
            }
        }