协调两个对象集合
我有一个表单,用户可以使用DataGrid修改对象集合。 打开表单时,我创建了原始集合的深层副本,如果按下“取消”按钮,则只丢弃该副本。
问题是,当按下确定按钮时,我必须协调可能的更改:
- 修改现有对象的属性
- 添加到集合中任何位置的新对象。
- 已删除现有对象。
- 现有对象重新排序。
因为我需要保留原始引用,所以我不能只清除集合并添加修改后的项目。
你知道一个简单的算法会同步两个这样的集合吗?
我正在使用C#3.5,因此可以使用LINQ。
我刚刚为我正在研究的项目制定了以下算法,我认为它符合您的要求。 它遵循以下步骤:
- 创建原始列表的浅表副本。
- 清除原始列表。
- 修改后的列表中的Foreach项目。
- 如果它找到原始对象将其添加到列表并更新它的属性。
- 如果不只是将其添加到列表中。
此方法维护新订单并重用原始引用,但要求您的对象具有唯一标识符。 我正在使用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 }