0

I have two lists. There are only one field difference. How to fill the lists with each other.

  [Serializable()] 
  public class Lst1
  {
        public string filed1 { get; set; }
        public Int16 filed2 { get; set; }
        .
        .
        .
        public Boolean filed100 { get; set; } 
  }

  [Serializable()] 
  public class Lst2
  {
        public string filed1 { get; set; }
        public Int16 filed2 { get; set; }
        .
        .
        .
        public Boolean filed100 { get; set; } 
        public string filed101 { get; set; }  
  }

List<Lst1> Lst1_ = new List<Lst1>();
List<Lst2> Lst2_ = new List<Lst2>();

I fill out lists from files. then,I need to fill out the list two from list one,There are many fields And I do not want to use the foreach loop.

It should be remembered that my previous class was already built and serialized and stored in a file. And now I need to transfer the previous information to the second class structure.

I do not want to use this loop!

foreach (var t in Lst1_)
            {
                Lst2_.Add(new lst2
                {
                    filed1 = t.filed1,
                    filed2 = t.filed2,
                    .
                    .
                    .
                    filed100 = t.filed100,
                    filed101 = "kk"
                }
            }
  • 1
    Can you explain more what you are trying to do? and what you tried? – Just code Oct 09 '18 at 13:18
  • Yeah, that's gonna be practically impossible without defining some kind of abstract super class which holds the shared fields. – nbokmans Oct 09 '18 at 13:19
  • 6
    Your classes have 100-101 string properties? Why so many? It looks to me like the data held by classes might be better represented as lists. – spender Oct 09 '18 at 13:19
  • 3
    Maybe consider [automapper](https://automapper.org/). Or maybe even just store all this in a `string[]`, it seems these are just field and a number so an array or `List` would make much more sense to me. – Liam Oct 09 '18 at 13:20
  • 3
    Poor class design, one for all – Tim Schmelter Oct 09 '18 at 13:20
  • Can you explain why you don't want to use a `foreach` loop? Do you mean you don't want to use reflection? – C.Evenhuis Oct 09 '18 at 13:23
  • 1
    Maybe class 2 should inherit from class 1 and only have one property more. – Tim Schmelter Oct 09 '18 at 13:23
  • I am pretty much of the opinion that once you reach for automapper then you've made a mistake in your design. – Liam Oct 09 '18 at 13:23
  • 1
    @Liam Amen to that. My default position with AM (after wading into so many abuses) is *"avoid"* – spender Oct 09 '18 at 13:24
  • 1
    If you dont want to type each field, you can iterate it with reflection – A.B. Oct 09 '18 at 13:26
  • @AnilBakirci My first list (lst2_) is already made and contains data. But after reading it, I have to transfer it to lst2_ – mohammad reza poushideh Oct 09 '18 at 13:30
  • what does *"previous class was already built and serialized and stored in a file"* mean? Classes are compiled, not stored in files? *"And now I need to transfer the previous information to the second class structure"* but your second class structure is virtually identical so why do you need a second class at all? – Liam Oct 09 '18 at 13:32
  • The second class is the class I currently use in my project. The first class was built last year and has data and I need that data and I want to transfer it to the second class(lst2_). – mohammad reza poushideh Oct 09 '18 at 13:37

3 Answers3

1

Is this what you want?

class Lst1
{
    public string filed1 { get; set; }
    public string filed2 { get; set; }
    public string filed3 { get; set; }
    public string filed4 { get; set; }
    public string filed5 { get; set; }
}

class Lst2
{
    public string filed1 { get; set; }
    public string filed2 { get; set; }
    public string filed3 { get; set; }
    public string filed4 { get; set; }
    public string filed5 { get; set; }
    public string filed6 { get; set; }
}

void CopyData()
{
        // test data
        List<Lst1> Lst1_ = new List<Lst1>()
        {
            new Lst1()
            {
                filed1 = "1",
                filed2 = "2",
                filed3 = "3",
                filed4 = "4",
                filed5 = "5",
            },
            new Lst1()
            {
                filed1 = "6",
                filed2 = "7",
                filed3 = "8",
                filed4 = "9",
                filed5 = "10",
            },
        };

        List<Lst2> Lst2_ = new List<Lst2>();

        foreach (var item in Lst1_)
        {
            Type type1 = item.GetType();
            PropertyInfo[] properties1 = type1.GetProperties();

            var current = new Lst2();
            Type type2 = current.GetType();
            PropertyInfo[] properties2 = type2.GetProperties();

            int k = 0;
            foreach (PropertyInfo property in properties1)
            {
                var value = property.GetValue(item, null);

                int n; 
                bool isNumeric = int.TryParse(value.ToString(), out n); 
                if (!isNumeric) 
                    value = "Your desired value"; 

                properties2[k].SetValue(current, value);
                k++;
            }

            Lst2_.Add(current);
        }
}

It copies everything from list 1 to list2.

A.B.
  • 2,374
  • 3
  • 24
  • 40
  • If it is what you want, please accept it as answer when you finish. – A.B. Oct 09 '18 at 13:47
  • At this point: "var value = property.GetValue(item, null);" If the number field like int32 is correct, but if the string it has error. – mohammad reza poushideh Oct 09 '18 at 13:56
  • I dont understand what you mean, you have only string properties, which number field? – A.B. Oct 09 '18 at 13:58
  • Sorry i said bad My class fields are String and Number and Boolean – mohammad reza poushideh Oct 09 '18 at 14:00
  • Your answer was absolutely correct. There is only one exception that, if the ordering of the fields in the two lists is not the same, makes a mistake. If we were able to sort the list by the name of the field, it would be great. like this: `foreach (PropertyInfo property in properties1.OrderBy(c=>c.Name))` – mohammad reza poushideh Oct 09 '18 at 14:50
0

No need to waste your time and money, AutoMapper can do it for you with only 2 lines of code:

using AutoMapper;

namespace ConsoleApp39
{
    class Program
    {
        static void Main (string[] args)
        {
            // fill list1 with data
            var list1 = new List1
            {
                Field1 = "test",
                Field2 = 5,
                Field3 = false,
            };

            // 1) configure auto mapper
            Mapper.Initialize (cfg => cfg.CreateMap<List1, List2> ());

            // 2) create list2 and fill with data from list1
            List2 list2 = Mapper.Map<List2> (list1);

            // fill extra fields
            list2.Field4 = new byte[] { 1, 2, 3 };
        }
    }

    public class List1
    {
        public string Field1 { get; set; }
        public int    Field2 { get; set; }
        public bool   Field3 { get; set; }
    }

    public class List2
    {
        public string Field1 { get; set; }
        public int    Field2 { get; set; }
        public bool   Field3 { get; set; }

        public byte[] Field4 { get; set; } // extra field
    }
}
apocalypse
  • 5,764
  • 9
  • 47
  • 95
0

Do Lst1 can inheritance from Lst2?

Something like this, the two lists:

[Serializable()]
public class Lst1
{
    public string filed1 { get; set; }
    public int filed2 { get; set; }
    public bool filed100 { get; set; }
}

[Serializable()]
public class Lst2 : Lst1
{
    public string filed101 { get; set; }
}

and one print extension

public static class CExtensions
{
    public static string PropertyList(this Lst1 obj)
    {
        var props = obj.GetType().GetProperties();
        var sb = new StringBuilder();
        foreach (var p in props)
        {
            sb.AppendLine(p.Name + ": " + p.GetValue(obj, null));
        }
        return sb.ToString();
    }
}

then using it:

class Program
{
    static void Main(string[] args)
    {
        const int I = 15;
        try
        {
            //init first list
            List<Lst1> Lst1_ = new List<Lst1>();
            Init(Lst1_);

            //print it
            Console.WriteLine("Lst1_");
            Console.WriteLine(new string('-', I));
            Lst1_.ForEach(x => Console.WriteLine(x.PropertyList()));
            Console.WriteLine(new string('=', I));
            Console.ReadKey();

            //init second list
            List<Lst1> Lst2_ = Lst1_.Cast<Lst1>().ToList(); //equivalent of two next lines
            //List<Lst1> Lst2_ = new List<Lst2>().ConvertAll(x => (Lst1)x);
            //Lst2_.AddRange(Lst1_);

            //add one more
            Lst2_.Add(new Lst2
            {
                filed1 = "101",
                filed2 = 202,
                filed100 = true,
                filed101 = "10100"
            });

            //and print 
            Console.WriteLine("Lst2_");
            Console.WriteLine(new string('-', I));
            Lst2_.ForEach(x => Console.WriteLine(x.PropertyList()));
            Console.WriteLine(new string('=', I));
            Console.ReadKey();


        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.ReadKey();
        }
    }

    private static void Init(List<Lst1> lst_)
    {
        for (int i = 1; i <= 3; i++)
        {
            lst_.Add(new Lst1
            {
                filed1 = i.ToString(),
                filed2 = 2 * i,
                filed100 = i % 2 == 0
            });
        }
    }
}

enjoy =)

oCcSking
  • 888
  • 21
  • 43