static int Main(string[] args)
        {
            var optionParser = new OptionParser();
            var options = new Options();

            if (!optionParser.TryParseOptions(args, out options))
            {
                Console.WriteLine("Expected usage: dotserver.windows <directoryToMonitor>");
                return -1;
            }

            // now set up a watcher;
            Console.WriteLine("Watching " + options.Directory + " for " + options.Filter);

            var watcherFactory = new FileSystemObservableFactory();
            var allFileChanges = watcherFactory.SequenceOfFileSystemEvents(options, throttleSpeed: 200);

            allFileChanges.Subscribe(s =>
            {
                var file = Path.GetFileName(s);
                Console.WriteLine("{0}: {1}", DateTime.Now.ToShortTimeString(), file);
                new DotCompiler(options.DotCompilerPath).Compile(s);
            });

            Console.WriteLine("Press enter to quit");
            Console.ReadLine();

            return 0;
        }
        public IObservable<string> SequenceOfFileSystemEvents(Options options, long throttleSpeed)
        {
            var watcher = new FileSystemWatcher(options.Directory);
            watcher.Filter = options.Filter;
            watcher.NotifyFilter =
                NotifyFilters.LastAccess |
                NotifyFilters.LastWrite |
                NotifyFilters.FileName |
                NotifyFilters.DirectoryName;

            var createdFiles = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                h => watcher.Created += h,
                h => watcher.Created -= h)
                .Select(x => x.EventArgs.FullPath);

            var changedFiles = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                h => watcher.Changed += h,
                h => watcher.Changed -= h)
                .Select(x => x.EventArgs.FullPath);

            var deletedFiles = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                h => watcher.Deleted += h,
                h => watcher.Deleted -= h)
                .Select(x => x.EventArgs.FullPath);

            var renamedFiles = Observable.FromEventPattern<RenamedEventHandler, RenamedEventArgs>(
                h => watcher.Renamed += h,
                h => watcher.Renamed -= h)
                .Select(x => x.EventArgs.FullPath);

            var allFileChanges = createdFiles
                .Merge(changedFiles)
                .Merge(deletedFiles)
                .Merge(renamedFiles)
                .Throttle(TimeSpan.FromMilliseconds(throttleSpeed));

            watcher.EnableRaisingEvents = true;

            return allFileChanges;
        }
        public bool TryParseOptions(string[] args, out Options options)
        {
            if (args.Length != 1)
            {
                options = null;
                return false;
            }

            var directory = args[0];

            if (!Directory.Exists(directory))
            {
                options = null;
                return false;
            }

            options = new Options
            {
                Directory = directory,
                Extension = ConfigurationManager.AppSettings["dotserver.dotextension"],
                DotCompilerPath = ConfigurationManager.AppSettings["dotserver.dotcompilerpath"]
            };
            return true;
        }