协调两个对象集合

我有一个表单,用户可以使用DataGrid修改对象集合。 打开表单时,我创建了原始集合的深层副本,如果按下“取消”按钮,则只丢弃该副本。

问题是,当按下确定按钮时,我必须协调可能的更改:

  • 修改现有对象的属性
  • 添加到集合中任何位置的新对象。
  • 已删除现有对象。
  • 现有对象重新排序。

因为我需要保留原始引用,所以我不能只清除集合并添加修改后的项目。

你知道一个简单的算法会同步两个这样的集合吗?

我正在使用C#3.5,因此可以使用LINQ。

我刚刚为我正在研究的项目制定了以下算法,我认为它符合您的要求。 它遵循以下步骤:

  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; ... } } 

祝好运。

为什么不保留原始的副本,并绑定到实际的集合。 如果绑定到实际集合,则表示没有对帐。 按下取消时,只需将原始副本替换为原始副本即可。 它基本上是你想要做的事情的倒置……但它应该更容易管理。

我处理这个问题的方式取决于具有唯一ID的对象集合。 我也通过存储库来处理这个问题,但为了简洁起见,我把它留了下来。 它类似于以下内容:

 public static void MergeFields(IEnumerable persistedValues, IEnumerable 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 }