Search code examples
c#genericsabstractionc#-8.0

Generic Method with Generic foreach


I have 2 Methods that are almost the same but have little differences and I want to make 1 Generic Method to do it all.

Method 1

public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<EvolucionCartera> data)
{
    List<DataGraficoNgxChart> series = new List<DataGraficoNgxChart> { };
    foreach (var item in data)
    {
        if (series.Exists(s => s.Name == item.Clasificacion))
        {
            var sub = series.Find(s => s.Name == item.Clasificacion);
            Series serie = new Series { Value = item.Monto, Name = item.Fecha };
            sub.Series.Add(serie);
        }
        else
        {
            DataGraficoNgxChart evolucionPatrimonio = new DataGraficoNgxChart
            {
                Name = item.Clasificacion,
                Series = new List<Series> { new Series { Value = item.Monto, Name = item.Fecha } }
            };
            series.Add(evolucionPatrimonio);
        }
    }
    return series.OrderBy(s => s.Name).ToList();
}

Method 2

public List<DataGraficoNgxChartInvertida> GenerarDataGraficoNgxChart(List<Rentabilidad> data)
{
    List<DataGraficoNgxChartInvertida> series = new List<DataGraficoNgxChartInvertida> { };
    foreach (var item in data)
    {
        if (series.Exists(s => s.Name == item.Fecha))
        {
            var sub = series.Find(s => s.Name == item.Fecha);
            SeriesInvertidaserie = new SeriesInvertida{ Value = item.Monto, Name = item.Clasificacion};
            sub.Series.Add(serie);
        }
        else
        {
            DataGraficoNgxChartInvertidaevolucionPatrimonio = new DataGraficoNgxChartInvertida
            {
                Name = item.Fecha,
                SeriesInvertida= new List<SeriesInvertida> { new Series { Value = item.Monto, Name = item.Clasificacion } }
            };
            series.Add(evolucionPatrimonio);
        }
    }
    return series.OrderBy(s => s.Name).ToList();
}

And my classes are:

    private class DataGraficoNgxChart
    {
        public string Name { get; set; }
        public List<Series> Series { get; set; }
    }
    private class DataGraficoNgxChartInvertida
    {
        public DateTime Name { get; set; }
        public List<SeriesInvertida> Series { get; set; }
    }
    private class Series
    {
        public decimal? Value { get; set; }
        public DateTime Name { get; set; }
    }
    private class SeriesInvertida
    {
        public decimal? Value { get; set; }
        public string Name { get; set; }
    }

So far, I managed to make the clases Generic:

    public class DataGraficoNgxChart<N, T>
    {
        public N Name { get; set; }
        public List<Series<T>> Series { get; set; }
    }
    public class Series<T>
    {
        public decimal? Value { get; set; }
        public T Name { get; set; }
    }

But I struggle doing the Generic Method:

    public List<DataGraficoNgxChart<N, T>> GenerarDataGraficoNgxChart<X, N, T>(List<X> data, Predicate<X> ejexName, b ejey ) // Trying to pass the parameters, but might be wrong
    {
        List<DataGraficoNgxChart<N, T>> series = new List<DataGraficoNgxChart<N, T>> { };
        foreach (var item in data)
        {
            if (series.Exists(s => s.Name == item.Clasificacion)) // item properties gives me error (obviously, it doesn't have a way to know them)
            {
                var sub = series.Find(s => s.Name == item.Clasificacion); // Other error here
                Series<T> serie = new Series<T> { Value = item.Monto, Name = item.Fecha }; // And here
                sub.Series.Add(serie);
            }
            else
            {
                DataGraficoNgxChart<N, T> evolucionPatrimonio = new DataGraficoNgxChart<N, T>
                {
                    Name = item.Clasificacion, // And here again
                    Series = new List<Series<T>> { new Series<T> { Value = item.Monto, Name = item.Fecha } } // And and again...
                };
                series.Add(evolucionPatrimonio);
            }
        }
        return series.OrderBy(s => s.Name).ToList();
    }

The code is wrong (its a WIP) but I don't know how to call the generic objects properties inside the for each.

This is my complete class so far with the old methods and the generic one.

using System;
using System.Collections.Generic;
using System.Linq;

namespace GpiWebApp.Services
{
    public interface INgxChartSpecification
    {
        List<DataGraficoNgxChart<N, T>> GenerarDataGraficoNgxChart<X, N, T>(List<X> data, Predicate<X> ejexName, b ejey);
        List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<RentabilidadClasificacion> data);
        List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<EvolucionCartera> data);
        List<DataGraficoNgxChartInvertida> GenerarDataGraficoInvertidoNgxChart(List<EvolucionCartera> data);
    }

    public sealed class NgxChartSpecification : INgxChartSpecification
    {
        public NgxChartSpecification()
        {
        }

        public List<DataGraficoNgxChart<N, T>> GenerarDataGraficoNgxChart<X, N, T>(List<X> data, Predicate<X> ejexName, b ejey) // Trying to pass the parameters, but might be wrong
        {
            List<DataGraficoNgxChart<N, T>> series = new List<DataGraficoNgxChart<N, T>> { };
            foreach (var item in data)
            {
                if (series.Exists(s => s.Name == item.Clasificacion)) // item properties gives me error (obviously, it doesn't have a way to know them)
                {
                    var sub = series.Find(s => s.Name == item.Clasificacion); // Other error here
                    Series<T> serie = new Series<T> { Value = item.Monto, Name = item.Fecha }; // And here
                    sub.Series.Add(serie);
                }
                else
                {
                    DataGraficoNgxChart<N, T> evolucionPatrimonio = new DataGraficoNgxChart<N, T>
                    {
                        Name = item.Clasificacion, // And here again
                        Series = new List<Series<T>> { new Series<T> { Value = item.Monto, Name = item.Fecha } } // And and again...
                    };
                    series.Add(evolucionPatrimonio);
                }
            }
            return series.OrderBy(s => s.Name).ToList();
        }

        public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<RentabilidadClasificacion> data)
        {
            List<DataGraficoNgxChart> series = new List<DataGraficoNgxChart> { };
            foreach (var item in data)
            {
                if (series.Exists(s => s.Name == item.dscArbol))
                {
                    var sub = series.Find(s => s.Name == item.dscArbol);
                    Series serie = new Series { Value = item.ValorCuota, Name = item.FechaCierre };
                    sub.Series.Add(serie);
                }
                else
                {
                    DataGraficoNgxChart evolucionPatrimonio = new DataGraficoNgxChart
                    {
                        Name = item.dscArbol,
                        Series = new List<Series> { new Series { Value = item.ValorCuota, Name = item.FechaCierre } }
                    };
                    series.Add(evolucionPatrimonio);
                }
            }
            return series.OrderBy(s => s.Name).ToList();
        }

        public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<EvolucionCartera> data)
        {
            List<DataGraficoNgxChart> series = new List<DataGraficoNgxChart> { };
            foreach (var item in data)
            {
                if (series.Exists(s => s.Name == item.Clasificacion))
                {
                    var sub = series.Find(s => s.Name == item.Clasificacion);
                    Series serie = new Series { Value = item.Monto, Name = item.Fecha };
                    sub.Series.Add(serie);
                }
                else
                {
                    DataGraficoNgxChart evolucionPatrimonio = new DataGraficoNgxChart
                    {
                        Name = item.Clasificacion,
                        Series = new List<Series> { new Series { Value = item.Monto, Name = item.Fecha } }
                    };
                    series.Add(evolucionPatrimonio);
                }
            }
            return series.OrderBy(s => s.Name).ToList();
        }

        public List<DataGraficoNgxChartInvertida> GenerarDataGraficoInvertidoNgxChart(List<EvolucionCartera> data)
        {
            List<DataGraficoNgxChartInvertida> series = new List<DataGraficoNgxChartInvertida> { };
            foreach (var item in data)
            {
                if (series.Exists(s => s.Name == item.Fecha))
                {
                    var sub = series.Find(s => s.Name == item.Fecha);
                    SeriesInvertida serie = new SeriesInvertida { Value = item.Monto, Name = item.Clasificacion };
                    sub.Series.Add(serie);
                }
                else
                {
                    DataGraficoNgxChartInvertida evolucionPatrimonio = new DataGraficoNgxChartInvertida
                    {
                        Name = item.Fecha,
                        Series = new List<SeriesInvertida> { new SeriesInvertida { Value = item.Monto, Name = item.Clasificacion } }
                    };
                    series.Add(evolucionPatrimonio);
                }
            }
            return series.OrderBy(s => s.Name).ToList();
        }

    }

    public class DataGraficoNgxChart<N, T>
    {
        public N Name { get; set; }
        public List<Series<T>> Series { get; set; }
    }

    public class Series<T>
    {
        public decimal? Value { get; set; }
        public T Name { get; set; }
    }

    public class DataGraficoNgxChart
    {
        public string Name { get; set; }
        public List<Series> Series { get; set; }
    }
    public class Series
    {
        public decimal? Value { get; set; }
        public DateTime Name { get; set; }
    }

    public class DataGraficoNgxChartInvertida
    {
        public DateTime Name { get; set; }
        public List<SeriesInvertida> Series { get; set; }
    }
    public class SeriesInvertida
    {
        public decimal? Value { get; set; }
        public string Name { get; set; }
    }

    public class RentabilidadClasificacion
    {
        public DateTime FechaCierre { get; set; }
        public decimal IdArbol { get; set; }
        public string dscArbol { get; set; }
        public decimal Patrimonio { get; set; }
        public decimal Aporet { get; set; }
        public decimal Utilidad { get; set; }
        public decimal Rentabilidad { get; set; }
        public decimal ValorCuota { get; set; }
        public decimal Distribucion { get; set; }
        public decimal Nivel { get; set; }
    }

    public class EvolucionCartera
    {
        public DateTime Fecha { get; set; }
        public string Clasificacion { get; set; }
        public decimal? Monto { get; set; }
        public decimal NivelArbol { get; set; }
    }

}

Any help-ideas?


Solution

  • With you updated code example, you could do this.

    Create a common interface:

    public interface IItem
    {
        string Lookupname { get; }
        DateTime Name { get; }
        decimal? Value { get; }
    }
    

    Create a new method GenerarDataGraficoNgxChart with a where constraint and let it use IItem properties instead of RentabilidadClasificacion/EvolucionCartera:

    public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart<T>(List<T> data)
    where T : IItem // added 
    {
        List<DataGraficoNgxChart> series = new List<DataGraficoNgxChart> { };
        foreach (var item in data)
        {
            if (series.Exists(s => s.Name == item.Lookupname)) // changed
            {
                var sub = series.Find(s => s.Name == item.Lookupname);  // changed
                Series serie = new Series { Value = item.Value, Name = item.Name };  // changed
                sub.Series.Add(serie);
            }
            else
            {
                DataGraficoNgxChart evolucionPatrimonio = new DataGraficoNgxChart
                {
                    Name = item.Lookupname,  // changed
                    Series = new List<Series> { new Series { Value = item.Value, Name = item.Name } }  // changed
                };
                series.Add(evolucionPatrimonio);
            }
        }
        return series.OrderBy(s => s.Name).ToList();
    }
    

    and of course, let RentabilidadClasificacion and EvolucionCartera implement the interface. I choose here for explicit interface implementation:

    public class RentabilidadClasificacion : NgxChartSpecification.IItem
    {
        public DateTime FechaCierre { get; set; }
        public decimal IdArbol { get; set; }
        public string dscArbol { get; set; }
        public decimal Patrimonio { get; set; }
        public decimal Aporet { get; set; }
        public decimal Utilidad { get; set; }
        public decimal Rentabilidad { get; set; }
        public decimal ValorCuota { get; set; }
        public decimal Distribucion { get; set; }
        public decimal Nivel { get; set; }
    
        #region Implementation of IItem
        string NgxChartSpecification.IItem.Lookupname => dscArbol;
        DateTime NgxChartSpecification.IItem.Name => FechaCierre;
        decimal? NgxChartSpecification.IItem.Value => ValorCuota;
    
        #endregion
    }
    
    public class EvolucionCartera : NgxChartSpecification.IItem
    {
        public DateTime Fecha { get; set; }
        public string Clasificacion { get; set; }
        public decimal? Monto { get; set; }
        public decimal NivelArbol { get; set; }
    
        #region Implementation of IItem
        DateTime NgxChartSpecification.IItem.Name => Fecha;
        decimal? NgxChartSpecification.IItem.Value => Monto;
        string NgxChartSpecification.IItem.Lookupname => Clasificacion;
    
        #endregion
    }
    

    Now you could create:

    public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<EvolucionCartera> data)
    {
        return GenerarDataGraficoNgxChart<EvolucionCartera>(data);
    } 
    public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<RentabilidadClasificacion> data)
    {
        return GenerarDataGraficoNgxChart<RentabilidadClasificacion>(data);
    }
    

    All classes, this compiles!

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace GpiWebApp.Services
    {
        public interface INgxChartSpecification
        {
            List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<RentabilidadClasificacion> data);
            List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<EvolucionCartera> data);
            List<DataGraficoNgxChartInvertida> GenerarDataGraficoInvertidoNgxChart(List<EvolucionCartera> data);
        }
    
        public sealed class NgxChartSpecification : INgxChartSpecification
        {
            public NgxChartSpecification()
            {
            }
    
            public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<EvolucionCartera> data)
            {
                return GenerarDataGraficoNgxChart<EvolucionCartera>(data);
            }
            public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart(List<RentabilidadClasificacion> data)
            {
                return GenerarDataGraficoNgxChart<RentabilidadClasificacion>(data);
            }
    
            public List<DataGraficoNgxChart> GenerarDataGraficoNgxChart<T>(List<T> data)
            where T : IItem // added 
            {
                List<DataGraficoNgxChart> series = new List<DataGraficoNgxChart> { };
                foreach (var item in data)
                {
                    if (series.Exists(s => s.Name == item.Lookupname)) // changed
                    {
                        var sub = series.Find(s => s.Name == item.Lookupname);  // changed
                        Series serie = new Series { Value = item.Value, Name = item.Name };  // changed
                        sub.Series.Add(serie);
                    }
                    else
                    {
                        DataGraficoNgxChart evolucionPatrimonio = new DataGraficoNgxChart
                        {
                            Name = item.Lookupname,  // changed
                            Series = new List<Series> { new Series { Value = item.Value, Name = item.Name } }  // changed
                        };
                        series.Add(evolucionPatrimonio);
                    }
                }
                return series.OrderBy(s => s.Name).ToList();
            }
    
            public interface IItem
            {
                string Lookupname { get; }
                DateTime Name { get; }
                decimal? Value { get; }
            }
    
            public List<DataGraficoNgxChartInvertida> GenerarDataGraficoInvertidoNgxChart(List<EvolucionCartera> data)
            {
                List<DataGraficoNgxChartInvertida> series = new List<DataGraficoNgxChartInvertida> { };
                foreach (var item in data)
                {
                    if (series.Exists(s => s.Name == item.Fecha))
                    {
                        var sub = series.Find(s => s.Name == item.Fecha);
                        SeriesInvertida serie = new SeriesInvertida { Value = item.Monto, Name = item.Clasificacion };
                        sub.Series.Add(serie);
                    }
                    else
                    {
                        DataGraficoNgxChartInvertida evolucionPatrimonio = new DataGraficoNgxChartInvertida
                        {
                            Name = item.Fecha,
                            Series = new List<SeriesInvertida> { new SeriesInvertida { Value = item.Monto, Name = item.Clasificacion } }
                        };
                        series.Add(evolucionPatrimonio);
                    }
                }
                return series.OrderBy(s => s.Name).ToList();
            }
    
        }
    
        public class DataGraficoNgxChart<N, T>
        {
            public N Name { get; set; }
            public List<Series<T>> Series { get; set; }
        }
    
        public class Series<T>
        {
            public decimal? Value { get; set; }
            public T Name { get; set; }
        }
    
        public class DataGraficoNgxChart
        {
            public string Name { get; set; }
            public List<Series> Series { get; set; }
        }
        public class Series
        {
            public decimal? Value { get; set; }
            public DateTime Name { get; set; }
        }
    
        public class DataGraficoNgxChartInvertida
        {
            public DateTime Name { get; set; }
            public List<SeriesInvertida> Series { get; set; }
        }
        public class SeriesInvertida
        {
            public decimal? Value { get; set; }
            public string Name { get; set; }
        }
    
        public class RentabilidadClasificacion : NgxChartSpecification.IItem
        {
            public DateTime FechaCierre { get; set; }
            public decimal IdArbol { get; set; }
            public string dscArbol { get; set; }
            public decimal Patrimonio { get; set; }
            public decimal Aporet { get; set; }
            public decimal Utilidad { get; set; }
            public decimal Rentabilidad { get; set; }
            public decimal ValorCuota { get; set; }
            public decimal Distribucion { get; set; }
            public decimal Nivel { get; set; }
    
            #region Implementation of IItem
            string NgxChartSpecification.IItem.Lookupname => dscArbol;
            DateTime NgxChartSpecification.IItem.Name => FechaCierre;
            decimal? NgxChartSpecification.IItem.Value => ValorCuota;
    
            #endregion
        }
    
        public class EvolucionCartera : NgxChartSpecification.IItem
        {
            public DateTime Fecha { get; set; }
            public string Clasificacion { get; set; }
            public decimal? Monto { get; set; }
            public decimal NivelArbol { get; set; }
    
            #region Implementation of IItem
            DateTime NgxChartSpecification.IItem.Name => Fecha;
            decimal? NgxChartSpecification.IItem.Value => Monto;
            string NgxChartSpecification.IItem.Lookupname => Clasificacion;
    
            #endregion
        }
    
    }