简体   繁体   English

C#在运行时将两个对象合并在一起

[英]C# merge two objects together at runtime

I have a situation where I am loading a very unnormalized record set from Excel. 我有一种情况,我从Excel加载一个非常不规范的记录集。 I pull in each row and create the objects from it one at a time. 我拉入每一行并一次创建一个对象。 each row could contain a company and / or a client. 每行可以包含公司和/或客户。

My issue is that multiple rows could have the same objects, so I may have already created it. 我的问题是多行可能有相同的对象,所以我可能已经创建了它。 I do a comparison to see if it is already in the list. 我做了一个比较,看看它是否已经在列表中。 If so I need to merge the two objects to ensure I have not gained any new information from the second row. 如果是这样,我需要合并这两个对象,以确保我没有从第二行获得任何新信息。

so: 所以:

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

so the first row would create a company object with an address of "myaddress". 所以第一行会创建一个地址为“myaddress”的公司对象。 The second row would create another company object (which by my rules is the same company as the name is the same), this also having a client reference and a phone number. 第二行将创建另一个公司对象(根据我的规则是与公司名称相同的公司),这也有客户参考和电话号码。

So I would know they are the same but need to ensure all the data is merged into one object. 所以我知道它们是相同的,但需要确保所有数据合并到一个对象中。

At the moment I am creating a utility class that takes both objects, (one being the primary and the other to be merged, so one has priority if there is a clash), it goes through each variable and assigns the values if there are any. 目前我正在创建一个实用程序类,它接受两个对象(一个是主要的,另一个是合并的,因此如果存在冲突,则一个具有优先级),它会遍历每个变量并分配值(如果有的话) 。 This is a bit boiler plate heavy and I was hoping there might be some utility I could utilize to do the manual work for me. 这是一个沉重的锅炉板,我希望可能有一些实用工具,我可以用来为我做手工工作。

The example has been simplified as there are a fair few other variables, some basic types and others that are more complex items. 这个例子已经简化,因为有一些其他变量,一些基本类型和其他更复杂的项目。

Reflection would work. 反思会起作用。 Something like: 就像是:

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

I'd try to split this up: divide and conquer. 我试图把它分开:分而治之。

First, read all the objects in one huge list. 首先,读取一个巨大列表中的所有对象。

In a second step, select distinct lists using your primary key, for example, the company name. 在第二步中,使用主键选择不同的列表,例如公司名称。 From the distinct list, use the item (the master) that has the largest number of fields set. 从不同列表中,使用具有最大字段数的项(主)。 Then, iterate over all the fields that are not yet in the master and merge their values in. LINQ will help you a lot in many of these steps without the need to code complicated algorithms manually. 然后,迭代尚未在主服务器中的所有字段并合并其值.LINQ将在许多这些步骤中帮助您,而无需手动编写复杂的算法。

This allows to customize the logic easily later, eg if you have a different set of 'primary keys' so to speak or if you want to do special comparisons of particular fields. 这允许稍后容易地定制逻辑,例如,如果您有一组不同的“主键”可以说或者您想要对特定字段进行特殊比较。

Try creating a string based hash table. 尝试创建基于字符串的哈希表。 Use a concatenation of a subset of fields that you consider to be the trigger for a duplicate record as the key. 使用您认为是重复记录触发器的字段子集的串联作为键。 The hashtable won't allow duplicates so you can use this error as a trigger to perform further processing. 哈希表不允许重复,因此您可以将此错误用作执行进一步处理的触发器。

Without knowing a lot more about your environment and requirements, this may be of no use. 在不了解您的环境和要求的情况下,这可能毫无用处。 But if you have some kind of database back-end available (even free client-side ones), you could store the data in a table and use the SQL Merge statement to update the data. 但是,如果您有某种数据库后端可用(甚至是免费的客户端),您可以将数据存储在表中并使用SQL Merge语句来更新数据。 A merge operation will either add or update a record as needed. 合并操作将根据需要添加或更新记录。 A trigger could further refine the operation. 触发器可以进一步细化操作。 This is a rather heavyweight solution, but if you already have some DBMS in the mix, it may be an easy method of implementing it. 这是一个相当重要的解决方案,但如果您已经在混合中使用了一些DBMS,那么它可能是一种实现它的简单方法。

When you retrieve the data from Excel, there is no need to create an object for each row.In fact, you'd probably want to go to an intermediate form that reads all the rows up front, then it creates the objects from there. 当您从Excel检索数据时,不需要为每一行创建一个对象。实际上,您可能希望转到一个读取前面所有行的中间表单,然后从那里创建对象。 Kibbey's solution using hash tables could work here as well. Kibbey使用哈希表的解决方案也适用于此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM