public override bool Equals(object obj) { ChaveAgrupar comp = obj as ChaveAgrupar; if (comp == null || comp.Itens.Length != Itens.Length) { return(false); } for (int i = 0; i < Itens.Length; i++) { if ((Itens[i] == null || comp.Itens[i] == null) && Itens[i] != comp.Itens[i]) { return(false); } else if (Itens[i] != null && comp.Itens[i] != null && Itens[i].GetType().IsArray&& comp.Itens[i].GetType().IsArray) { List <object> t = new List <object>(); foreach (object o in (Itens[i] as IEnumerable)) { t.Add(o); } List <object> c = new List <object>(); foreach (object o in (comp.Itens[i] as IEnumerable)) { c.Add(o); } if (t.Count != c.Count) { return(false); } for (int j = 0; j < t.Count; j++) { if ((t[j] == null || c[j] == null) && t[j] != c[j]) { return(false); } else if (t[j] != null && c[j] != null && !t[j].Equals(c[j])) { return(false); } } } else if (Itens[i] != null && comp.Itens[i] != null && !Itens[i].Equals(comp.Itens[i])) { return(false); } } return(true); }
/// <summary> /// Agrupa um IEnumerable<T>. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="itens">Os itens que serão agrupados.</param> /// <param name="propriedadesAgrupar">As propriedades que serão usadas como agrupamento.</param> /// <param name="propriedadesSomar">As propriedades que serão somadas.</param> /// <param name="parametrosConstrutorT">Os parâmetros para o método construtor de um objeto do tipo T.</param> /// <returns></returns> public static IEnumerable <T> Agrupar <T>(IEnumerable <T> itens, string[] propriedadesAgrupar, string[] propriedadesSomar, params object[] parametrosConstrutorT) { // Retorna a lista se não houver propriedades para agrupar if (itens == null || propriedadesAgrupar == null || propriedadesAgrupar.Length == 0) { return(itens); } Dictionary <ChaveAgrupar, T> agrupamento = new Dictionary <ChaveAgrupar, T>(); PropertyInfo[] pa = null, ps = null; foreach (T item in itens) { if (pa == null) { pa = GetPropriedades(item, propriedadesAgrupar); } if (ps == null) { List <PropertyInfo> p = new List <PropertyInfo>(GetPropriedades(item, propriedadesSomar)); ps = p.FindAll(x => x.PropertyType.IsValueType || x.PropertyType == typeof(string)).ToArray(); } ChaveAgrupar chave = new ChaveAgrupar(); chave.Itens = GetValues(item, pa); if (!agrupamento.ContainsKey(chave)) { T novo = Clonar <T>(item, parametrosConstrutorT); agrupamento.Add(chave, novo); } else { foreach (PropertyInfo p in ps) { if (p.PropertyType.IsValueType) { decimal valor = Conversoes.ConverteValor <decimal>(p.GetValue(agrupamento[chave], null)); valor += Conversoes.ConverteValor <decimal>(p.GetValue(item, null)); // Seta o valor da propriedade somente se ela tiver permissão para isso. if (p.CanWrite) { p.SetValue(agrupamento[chave], Conversoes.ConverteValor(p.PropertyType, valor), null); } } else if (p.PropertyType == typeof(string)) { string valorAtual = p.GetValue(agrupamento[chave], null) as string; string valorNovo = p.GetValue(item, null) as string; if (valorAtual == null) { valorAtual = ""; } if (valorNovo == null) { valorNovo = ""; } // Seta o valor da propriedade somente se ela tiver permissão para isso. if (p.CanWrite) { p.SetValue(agrupamento[chave], (valorAtual + "," + valorNovo).TrimStart(','), null); } } } } } T[] retorno = new T[agrupamento.Count]; agrupamento.Values.CopyTo(retorno, 0); return(retorno as IEnumerable <T>); }