Каков наилучший OO Design Pattern для обработки объектов реестра Windows (или файловой системы)? - PullRequest
1 голос
/ 24 июля 2010

Я строю один или два класса на основе StdRegProv для обработки реестра Windows через класс COM PHP.Для ссылки на все известные методы и типы StdRegProv, см .: http://msdn.microsoft.com/en-us/library/aa393664%28v=VS.85%29.aspx. (Даже не начинайте с того, что мне нужно знать, что тип Reg именованного значения просто для того, чтобы получить или установить его значение. IЯ уже нашел обходные пути для этой проблемы, но он требует Enuming через весь родительский ключ.)

Я присваиваю каждый ключ или именованное значение объекту PHP с его собственными уникальными свойствами и методами, предназначенными для обработки общихфункции реестра - перечислять именованные значения в ключе, перечислять подключи, добавлять / обновлять ключи и именованные значения и т. д. Я предвижу проблему, если во время работы моего скрипта другой процесс или действие моего кода может изменить пути реестра ключейили все именованные значения, или удалите их все полностью, тем самым разрушая любые существующие объекты на их основе - проблема, аналогичная той, с которой можно столкнуться при работе с реальными объектами файловой системы.За исключением реестра, блокировка отсутствует.

Например, если я удаляю имя реестра с именем, которое ранее было указано в объекте ключевого содержимого, который я создал ранее, этот объект содержимого ключа может лгать и все равно сообщать мне, чтоназванное значение существовало.Или, если бы я изменил значение чего-то, что другой процесс уже удалил или переместил, это создаст или перезапишет что-то в реестре, что потенциально может испортить мою ОС.

Вопрос в том, зная, что ключи и названызначения могут изменяться без уведомления, какой шаблон проектирования ОО лучше всего подходит для работы с Реестром (или объектами файловой системы в этом отношении)?

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

$key->value($name_or_index)->name; // get or set name
$key->value($name_or_index)->type; // get or set type
$key->value($name_or_index)->value; // get or set value
$key->value($name_or_index)->delete(); // delete this value, then destroys itself
$key->add_value($new_name, $reg_type, $value);
$key->parent; // get or set parent key path
$key->name; // get or set name
$key->delete();  // deletes key, unsets all child objects, nulls itself out
Reg::add_key($path); // abstract factory API returning new key as object
Reg::get_key($path); // abstract factory API returning existing key as object

Reg мастер-класс также содержит единый статический интерфейс COM, к которому имеют доступ все другие объекты, и является тем, из чего все остальные классы получены.Я предполагаю, что он также может содержать все методы для непосредственного взаимодействия с Реестром и все методы ведения журнала / отказоустойчивости.В этом смысле это был бы абстрактный API-интерфейс фабрики, и я позволил бы сохранять другие производные классы довольно маленькими.

Как предполагает MainMa ниже, любой доступ к ключу или значению будет получать значения непосредственно из реестра, чтобы избежатьлюбое нежелательное поведение "кэша".И у меня при запуске WIN будет установлен отказоустойчивый файл .reg, который будет защищать любые незавершенные транзакции, написанные моим сценарием.Если мой сценарий завершится успешно, он удалит этот файл .reg и загрузочную запись.В противном случае, если питание отключится на полпути, я буду в безопасности.

Полагаю, это лучший дизайн ...?

1 Ответ

2 голосов
/ 24 июля 2010

Почему бы не загрузить данные "по запросу"?Доступ к списку дочерних узлов или одного узла, когда вам нужно.Избегание предварительно загруженных данных или данных, загруженных слишком рано, уменьшит количество устаревших записей .

Поскольку устаревшие записи могут все еще существовать (т. Е. Если вы загрузили список дочерних узлов 1 мс назад), нет никакой гарантии, что каждый ребенок все еще там), перепроверять достоверность данных при каждой модификации .Например, если вы:

  1. читаете список дочерних узлов, затем
  2. ищите в списке узел, затем
  3. для каждого соответствующего узлазаменяя значение,

вы не можете проверять действительные данные во втором состоянии, но вы ДОЛЖНЫ проверить, существует ли узел в третьем состоянии, перед заменой значения. Если проверка не пройдена, выдается исключение .

Для реестра не существует такой вещи, как транзакции .Но вы можете попытаться сделать что-то похожее, гораздо более простое, в зависимости от контекста.Если вы сохраняете некоторые ключи в реестре и должны быть уверены, что эти ключи тем временем не изменены, сохраните существующие значения, начните сохранение, а когда закончите, перепроверьте значения. Если они неверны, вернитесь к предыдущему состоянию (сохраняя значения, измененные другой программой во время транзакции).

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

...