【问题标题】:Adding to reflected Dictionaries添加到反射字典
【发布时间】:2018-05-17 20:01:18
【问题描述】:

我有一个像这样的遗留类:

public class LegacyBusinessObject
{
....(100 similar fields in total)
    public Dictionary<string, string> SomeBusinessValue1 = new Dictionary<string, string>();
    public Dictionary<string, long> SomeBusinessValue2 = new Dictionary<string, long>();
    public Dictionary<string, decimal> SomeBusinessValue3 = new Dictionary<string, decimal>();
....
}

而字符串键表示该值来自的提供者。

因此,对于上下文:“SomeBusinessValue1”可能是重量测量值,具体取决于执行此操作的实验室。

我想使用反射将这些怪物中的几个合并为一个对象:

    public LegacyBusinessObject Merge(Dictionary<string, LegacyBusinessObject> objects)
    {
        var result = new LegacyBusinessObject();
        //Loop through all the business object's fields
        foreach (var prop in typeof(LegacyBusinessObject).GetFields())
        {
            //Second loop through all the individual objects from different providers
            foreach (var ep in objects)
            {
                //Here I would need to test for all possivle value types that could 
                //be in the dictionary: <string, string>, <string, long>...
                //then cast to it and invoke the Add method like this:
                var propDictionary = prop.GetValue(result) as Dictionary<string, string>;
                propDictionary.Add(ep.Key, ep.Value);
            }
        }
        return result;
    }

现在这种方法需要我为 propDictionary 做很多笨拙的转换。 (我还尝试构建匹配的 keyvaluepair 和一个 Activator 来实例化它;但我找不到将其添加到另一个字典的方法)

您能想出一种更好的方法来执行此合并,它采用任意字典值类型吗?

更多上下文:

我得到了一个 LegacyBusinessObject Obj1,其中包含来自实验室 A 和实验室 B 的数据,这些数据存储在字典中。不,我正在清理数据库并发现另一个 LegacyBusinessObject Obj2 具有来自 Lab C 和 Lab D 的数据。事实证明,在摄取过程中出现错误,并且 Obj1 和 Obj2 用于同一产品并且错误地存储在两个不同的旧版业务对象。我现在想合并数据以获得一个新的 LegacyBusinessObject 与从实验室 A 到 D 的数据

【问题讨论】:

  • 是的,我可以(简而言之,reflection),但您需要更准确地说出您希望 output 对象的样子。从信息层面讲,每个提供商都有一个stringSomeBusinessValue、一个longSomeBusinessValue2,等等——所以当你收集所有这些不同类型的商业价值时,你想把它们放在哪里? Edit that information into your q,您可以得到答复。
  • 你为什么要转换成 propDictionary 然后添加到同一个字典 propDictionary ?
  • @AakashM 我添加了一些上下文以进行澄清

标签: c#


【解决方案1】:

不清楚你到底在问什么,但是:

public static LegacyBusinessObject Merge(Dictionary<string, LegacyBusinessObject> objects)
{
    var result = new LegacyBusinessObject();

    foreach (var prop in typeof(LegacyBusinessObject).GetFields())
    {
        var propDictionaryNew = (IDictionary)prop.GetValue(result);

        foreach (var dict in objects)
        {
            var propDictionaryOld = (IDictionary)prop.GetValue(dict.Value);

            foreach (DictionaryEntry de in propDictionaryOld)
            {
                propDictionaryNew[de.Key] = de.Value;

                // Or: 
                //((IDictionary)result).Add(de.Key, de.Value);
                // But be aware of exceptions if de.Key is present in multiple dictionaries
            }
        }
    }

    return result;
}

然后,测试它:

var lbo1 = new LegacyBusinessObject
{
    SomeBusinessValue1 = new Dictionary<string, string> { { "A1", "A2" }, { "B1", "B2" } },
    SomeBusinessValue2 = new Dictionary<string, long> { { "C1", 1 }, { "D1", 2 } },
    SomeBusinessValue3 = new Dictionary<string, decimal> { { "E1", 3 }, { "F1", 4 } },
};

var lbo2 = new LegacyBusinessObject
{
    SomeBusinessValue1 = new Dictionary<string, string> { { "G1", "G2" }, { "H1", "H2" } },
    SomeBusinessValue2 = new Dictionary<string, long> { { "I1", 5 }, { "J1", 6 } },
    SomeBusinessValue3 = new Dictionary<string, decimal> { { "K1", 7 }, { "L1", 8 } },
};

var result = Merge(new Dictionary<string, LegacyBusinessObject> { { "X", lbo1 }, { "Y", lbo2 } });

我在这里作弊了...Dictionary&lt;,&gt; 实现了预泛型接口IDictionary(与IDictionary&lt;,&gt; 不同),它使用object 作为键和值。这样我就不必支持不同的值类型。将反射与泛型集合一起使用时,一个很好的技巧是查看非泛型接口是否足以满足您的需求(因为使用反射它们更容易处理)。

【讨论】:

  • 完美!我应该更仔细地检查接口。
猜你喜欢
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多