Шаблон дизайна для заказа чувствительных звонков - PullRequest
3 голосов
/ 21 февраля 2010

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

public interface IDirectorySource
{
    IEnumerable<IDirectoryEntry> GetChanges(IList<string> attributes, IChangeToken token);
}

Я хочу предоставить перечислитель вместо списка, чтобы избежать ненужного выделения памяти, но моя проблема в том, что я также хочу вернуть новый IChangeToken, который содержит новую информацию о состоянии, необходимую для следующего вызова GetChanges (делать инкрементные обновления). Код изменения должен быть рассчитан после перечисление завершено, поскольку кто-то другой мог обновлять каталог между различными вызовами.

Я думал о том, чтобы иметь второй параметр IChangeToken, который получает новый токен, но это не очень приятно (и не будет согласованным, так как токен будет возвращен немедленно, но не может быть заполнен, пока не завершится перечисление). ) .. И я думал о возврате чего-то вроде «IChangeSet» -интерфейса, который содержит метод GetEnumerator и метод GetToken, но проблема все еще в том, что последующие вызовы метода перечислителя возвращают разные данные (и, следовательно, имеют разные changetokens ).

Как я могу спроектировать интерфейс, который делает невозможным для пользователя моего интерфейса неправильное использование его в отношении моего перечислителя GetChanges и получения соответствующего ChangeToken?

Надеюсь, мой вопрос имеет смысл ...;) .. Мне было трудно понять, какой заголовок использовать для моего вопроса ...;)

Ответы [ 2 ]

1 голос
/ 21 февраля 2010

В функциональных языках программирования существует структура, называемая Tuple. Здесь я считаю, что Tuple - лучший выбор - кортеж, согласно дизайну, означает, что между его элементами нет никаких связей. Текущая версия .NET Framework (3.5) не поддерживает кортежи, но следующая (4.0) поддерживает. При необходимости вы всегда можете внедрить Tuple самостоятельно - ничего страшного. К сожалению, в C # отсутствует языковая поддержка для кортежей, но, например, в F # есть.

Итак, чтобы подвести итог, сделайте ваш интерфейс следующим образом:

Tuple<IEnumerable<IDirectoryEntry>, IChangeToken> GetChanges(IList<string> attributes, IChangeToken token);
0 голосов
/ 22 февраля 2010

Я попробовал подход с использованием "IChangeSet", о котором я думал в своем первоначальном вопросе. В этом сценарии интерфейс IDirectorySource выглядит следующим образом:

public interface IDirectorySource
{
    IChangeSet GetChanges(IList<string> attributes, IChangeToken token);
}

И реализовал IChangeSet-интерфейс, который выглядит так:

public interface IChangeSet : IEnumerable<IDirectoryEntry>
{
    IChangeToken GetToken();
}

Это позволяет писать клиентский код, который выглядит примерно так:

IChangeSet result = source.GetChanges(attributes, token);

foreach (IDirectoryEntry entry in result) {
    // Do something with the data...
}

IChangeToken resultToken = result.GetToken();

Несмотря на то, что это позволяет вызвать метод "GetToken ()" перед перечислением (что было бы неправильно), я мог бы вернуть старый токен, если функция вызывается до завершения перечисления.

Не чувствует себя на 100%, но это лучшее, что я могу придумать в это время ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...