Согласование двух коллекций объектов - PullRequest
1 голос
/ 29 октября 2009

У меня есть форма, где пользователи могут изменять коллекцию объектов, используя DataGrid. Когда форма открыта, я создаю глубокую копию оригинальной коллекции, а если нажать кнопку «Отмена», я просто отбрасываю эту копию.

Проблема в том, что когда нажата кнопка ОК, я должен согласовать изменения, которые могут быть:

  • Изменены свойства существующих объектов
  • Новые объекты добавлены в любое место в коллекции.
  • Существующие объекты удалены.
  • Существующие объекты переупорядочены.

Поскольку мне нужно сохранить исходные ссылки, я не могу просто очистить коллекцию и добавить измененные элементы.

Знаете ли вы простой алгоритм, который синхронизировал бы две коллекции, подобные этой?

Я использую C # 3.5, поэтому LINQ доступен.

Ответы [ 3 ]

1 голос
/ 29 октября 2009

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

public static void MergeFields(IEnumerable<TYPE1> persistedValues, IEnumerable<TYPE1> newValues)
{
    var leftIds = persistedValues.Select(x => x.Id).ToArray();
    var rightIds = newValues.Select(x => x.Id).ToArray();

    var toUpdate = rightIds.Intersect(leftIds).ToArray();
    var toAdd = rightIds.Except(leftIds).ToArray();
    var toDelete = leftIds.Except(rightIds).ToArray();

    foreach(var id in toUpdate){
        var leftScope = persistedValues.Single(x => x.ID == id);
        var rightScope = newValues.Single(x => x.ID == id);

        // Map appropriate values from rightScope over to leftScope
    }

    foreach(var id in toAdd) {
        var rightScope = newValues.Single(x => x.ID == id);
        // Add rightScope to the repository
    }

    foreach(var id in toDelete) {
        var leftScope = persistedValues.Single(x => x.ID == id);
        // Remove leftScope from the repository
    }

    // persist the repository
}
1 голос
/ 29 октября 2009

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

0 голосов
/ 29 октября 2009

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

  1. Создает поверхностную копию исходного списка.
  2. Очищает исходный список.
  3. Элемент Foreach в измененном списке.
    1. Если он находит оригинальный объект, он добавляет его в список и обновляет его свойства.
    2. Если не просто добавить его в список.

Этот метод поддерживает новый порядок и повторно использует исходные ссылки, но требует, чтобы ваши объекты имели уникальный идентификатор. Для этого я использую Guid.

var originalPersons = m_originalList.ToList();
m_originalList.Clear();
foreach (var modifiedPerson in m_modifiedList)
{
    var originalPerson = originalPersons.FirstOrDefault(c => c.ID == modifiedPerson.ID);
    if (originalPerson == null)
        m_originalList.Add(modifiedPerson);
    else
    {
        m_originalList.Add(originalPerson);
        originalPerson.Document = modifiedPerson.Document;
        originalPerson.Name = modifiedPerson.Name;
        ...
    }
}

Удачи.

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