Windows Management Instrumentation. События в WMI. Библиотека классов MyWMI. Особенности работы с большим деревом, страница 14

{

  tree.EndUpdate();  Cursor = Cursors.Default;

  if (Текуший узел (узнайте его из параметра) — не корневой)

  {

    dirWatcher.Path = Из узла узнайте путь и вычлените из файлового пути логический диск

                                                          (используйте для этого метод класса Path) Все в одной строке кода!!

    dirWatcher.EnableRaisingEvents = true;

  }

}

Корневой узел (My Computer) следует обойти — он явно все портит. Итак, мы выставили сторожевую собаку по кличке dirWatcher из породы FileSystemWatcher. Мы приказали ей сторожить один из логических дисков. Какой? Собака залает, когда произойдут какие-либо изменения в этом (активизированном в нашем дереве) диске. При этом она (dirWatcher, конечно) вызовет одну из существующих, но пока не реализованных нами функций: dirWatcher_Changed или dirWatcher_Renamed. Пора за них браться.

В качестве упражнения укажите то место в программе, где собака получила наставление (делегата с заданием). Как создан делегат? Какой тип имеет его задание? Сколько действующих лиц (наблюдателей, или собак, делегатов, заданий) уже декларировано? Как изменить количество каждого?

  private void dirWatcher_Changed (object sender, FileSystemEventArgs e)

  {

    string msg = "";

    switch (в зависимости от типа изменений (узнайте из параметра))

    {

    case WatcherChangeTypes.Created: // Пока не знаем, что делать

      break;

    case WatcherChangeTypes.Deleted:

      if (NodeExists (файловый путь узнайте его из параметра) // Если удаляемый узел существует

        searchNode.Remove();

      msg = "Directory deleted: ";

      break;

    }

    UpdateStatusBar (Color.LightSkyBlue, msg + e.Name);   

  }

}

Логика реакции довольно прозрачна, но надо разработать функцию NodeExists. Очевидно, она должна возвращать true или false, в зависимости от того, есть ли узел с указанным путем в нашем дереве или нет. Вы помните, что дерево заполняется постепенно? Если удаляемый (кем-то и где-то) файл расположен в файловой системе глубоко, то в нашем дереве его может и не быть.

Поиск в дереве

Итак, нам надо искать узел в дереве. Поиск в дереве — это излюбленная тема многих учебников по алгоритмам и структурам данных. Рекурсия здесь прямо напрашивается. Если вы сами напишите рекурсивную функцию, то получите большое удовольствие (это правда, я проверял). Рекурсивная функция сильно загружает стек, так как в нем хранятся все локальные переменные промежуточных вызовов. Параметры функции — это локальные переменные, поэтому рекурсивная функция должна иметь как можно меньше параметров.

Другой важный момент: при разработке рекурсивной процедуры следует задать ее глубину — барьер, при достижении которого рекурсия заканчивается. В нашем случае считайте, что барьером является найденный узел. Если ссылка searchNode (она уже есть в классе формы) не нулевая, то узел найден и пора возвращаться. Учитывая сказанное, напишем функцию NodeExists (она готовит рекурсию).

private bool NodeExists (string path)

{

  searchPath = path.ToLower().TrimEnd('\\');  // Искомый путь. TrimEnd нужен при поиске корневых директорий

  searchNode = null;     // Устанавливаем барьер. (Пока узел не найден)

  FindRecursive (root);  // Эта функция должна искать узел (рекурсивно)

  return searchNode != null; // Нашли  или не нашли

}

Теперь создайте функцию рекурсивного поиска. Она должна вызывать чувство эстетического удовольствия.

private bool FindRecursive (TreeNode node) // true - либо нашли, либо нет смысла искать (так как целина)

{

  foreach (Для каждого узла из коллекции узлов, вложенных в node)

  {

    string cur = Полный файловый путь текущего узла (узнайте из самого узла)

                                            (но выкиньте из него"My Computer"/ Здесь понадобится rootLength

    if (searchPath равна текущему cur) // Нашли

    {

      searchNode = Запоминаем текущий узел;

      return true;

    }