mardi 23 juin 2015

Merging Dictionaries using generics in C#

I am looking to implement a method that is capable of merging 2 dictionaries using generics. I've seen several great answers on SO already, but none of which are recursive. As in, what if the value of the dictionaries is another dictionary...

So I came up with this:

using System;
using System.Collections.Generic;
using System.Reflection;

namespace MyNameSpace
{
    /// <summary>
    /// This class contains helpful methods for manipulating collections.
    /// Utilizes .NET 4.0 features.
    /// </summary>
    public class DictionaryHelper
    {
        #region Dictionary
        /// <summary>
        /// Unionise two dictionaries of generic types.
        /// Duplicates take their value from the leftmost dictionary.
        /// </summary>
        /// <typeparam name="T1">Generic key type</typeparam>
        /// <typeparam name="T2">Generic value type</typeparam>
        /// <param name="D1">Dictionary 1</param>
        /// <param name="D2">Dictionary 2</param>
        /// <returns>The combined dictionaries.</returns>
        /// <remarks>Never overload this method. Or else!</remarks>
        public static Dictionary<T1, T2> UnionDictionaries<T1, T2>(Dictionary<T1, T2> D1, Dictionary<T1, T2> D2)
        {
            Dictionary<T1, T2> rd = new Dictionary<T1, T2>(D1);
            foreach (var key in D2.Keys)
            {
                if (!rd.ContainsKey(key))
                    rd.Add(key, D2[key]);
                else
                {
                    if (rd[key].GetType().GetGenericTypeDefinition() == typeof(Dictionary<,>))
                    {
                        MethodInfo info = typeof(DictionaryHelper).GetMethod("UnionDictionaries", BindingFlags.Public | BindingFlags.Static);
                        rd[key] = (T2)info.Invoke(null, new object[] { rd[key], D2[key] });
                    }
                    else if(rd[key].GetType().GetGenericTypeDefinition() == typeof(HashSet<>))
                    {
                        MethodInfo info = typeof(HashSet<>).GetMethod("UnionWith", BindingFlags.Public);
                        info.Invoke(rd[key], new object[]{D2[key]});
                    }
                }
            }
            return rd;
        }
        #endregion
    }
}

I was just wondering how safe/sane this is and if there are any other ways of doing this?





Aucun commentaire:

Enregistrer un commentaire