【问题标题】:C# merge two objects together at runtimeC# 在运行时将两个对象合并在一起
【发布时间】:2010-03-07 13:38:41
【问题描述】:

我有一种情况,我正在从 Excel 加载一个非常非规范化的记录集。我拉入每一行并一次创建一个对象。每行可以包含一个公司和/或一个客户。

我的问题是多行可能有相同的对象,所以我可能已经创建了它。我做一个比较,看看它是否已经在列表中。如果是这样,我需要合并这两个对象以确保我没有从第二行获得任何新信息。

所以:

company   - client   - address   - phone
----------------------------------------
mycompany -          - myaddress - 
mycompnay - myclient -           - myphone

所以第一行将创建一个地址为“myaddress”的公司对象。 第二行将创建另一个公司对象(根据我的规则,它是同一家公司,因为名称相同),这也有一个客户参考和一个电话号码。

所以我会知道它们是相同的,但需要确保所有数据都合并到一个对象中。

目前,我正在创建一个实用程序类,它接受两个对象(一个是主要对象,另一个是要合并的对象,因此如果发生冲突,则一个具有优先级),它会遍历每个变量并在以下情况下分配值有的。这有点像样板,我希望可能有一些实用程序可以用来为我做手动工作。

该示例已被简化,因为还有一些其他变量,一些基本类型和其他更复杂的项目。

【问题讨论】:

  • 你确定总是有最多 2 个对象需要合并吗?如果相同的列/属性被定义两次会发生什么?忽略一个听起来很危险!?
  • 他们这样我正在迭代我的收藏,同时我会在找到的每个匹配项中合并。理论上,集合中可能有多个匹配项,但每次合并都会一次完成一个。如果用户输入了错误的数据,那么我不得不因为多个字段而失去一些价值,我无论如何都看不到。

标签: c#


【解决方案1】:

反射会起作用。比如:

public static void MergeWith<T>(this T primary, T secondary) {
    foreach (var pi in typeof(T).GetProperties()) {
       var priValue = pi.GetGetMethod().Invoke(primary, null);
       var secValue = pi.GetGetMethod().Invoke(secondary, null);
       if (priValue == null || (pi.PropertyType.IsValueType && priValue.Equals(Activator.CreateInstance(pi.PropertyType)))) {
          pi.GetSetMethod().Invoke(primary, new object[]{secValue});
       }
    }
}

【讨论】:

  • 通用而优雅。但不知何故,它让我的脊椎不寒而栗。
  • 向您致敬,先生! ;-)
  • 出于某种原因,priValue == Activator.CreateInstance(pi.PropertyType) 为值类型返回 false。相反,priValue.Equals(Activator.CreateInstance(pi.PropertyType)) 会产生正确的输出。
  • 优雅,但它如何处理像字符串这样的引用类型,因为它有这个子句“pi.PropertyType.IsValueType”。
【解决方案2】:

我会尝试拆分:分而治之。

首先,读取一个巨大列表中的所有对象。

在第二步中,使用您的主键选择不同的列表,例如公司名称。从不同的列表中,使用具有最多字段集的项目(主)。然后,遍历所有尚未在 master 中的字段并将它们的值合并到其中。LINQ 将在许多这些步骤中为您提供很多帮助,而无需手动编写复杂的算法。

这允许稍后轻松自定义逻辑,例如如果您有一组不同的“主键”,或者您想对特定字段进行特殊比较。

【讨论】:

    【解决方案3】:

    尝试创建一个基于字符串的哈希表。使用您认为是重复记录触发器的字段子集的串联作为键。哈希表不允许重复,因此您可以将此错误用作触发器来执行进一步处理。

    【讨论】:

      【解决方案4】:

      如果不了解更多有关您的环境和要求的信息,这可能毫无用处。但是,如果您有某种可用的数据库后端(甚至是免费的客户端),您可以将数据存储在一个表中并使用SQL Merge 语句来更新数据。合并操作将根据需要添加或更新记录。触发器可以进一步细化操作。这是一个相当重量级的解决方案,但如果您已经有一些 DBMS,它可能是一种简单的实现方法。

      【讨论】:

        【解决方案5】:

        当您从 Excel 中检索数据时,无需为每一行创建一个对象。事实上,您可能希望转到一个中间表单,预先读取所有行,然后创建对象从那里。 Kibbey 使用哈希表的解决方案也可以在这里工作。

        【讨论】:

        • 嗨,对不起,为了方便起见,我稍微简化了我的例子。我直接将整个 xls 读入数据表,然后为每一行创建一个结构来进行处理,而不是直接处理它。
        猜你喜欢
        • 2018-11-23
        • 1970-01-01
        • 2015-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 1970-01-01
        • 2017-08-05
        相关资源
        最近更新 更多