简体   繁体   中英

Concatenate the properties of a List<Class> and write to file in C#

I have a variable defined as List<Car>. I want to concatenate the properties of the individual class in a list with some delimiter and write to file without looping on properties.

Example:

    public class Car
    {
        public int CarId { get; set; }
        public string Brand { get; set; }
        public string Model { get; set; }
        public string Color { get; set; }
    }

    public void AssignData()
    {
        List<Car> cars = new List<Car>();
        cars.Add(new Car { CarId = 1, Brand = "Hundai", Model = "i10", Color = "White" });
        cars.Add(new Car { CarId = 2, Brand = "Hundai", Model = "i20", Color = "Blue" });
    }

My expected output would be a text file with "," as a delimiter.

Exected output:

1,Hundai,i10,White 2,Hundai,120,Blue

I have tried the below code using propertyinfo class, but i feel it is not effeicient as there is a nested loop

Below is the one which tried:

using (StreamWriter file = new StreamWriter(@"D:\WriteLines.txt", true))
            {
                foreach (Car car in allCars)
                {
                    PropertyInfo[] properties = car.GetType().GetProperties();
                    string fullLine = string.Empty;
                    foreach (PropertyInfo property in properties)
                    {
                        fullLine += property.GetValue(car, null).ToString() + ",";
                    }
                    file.WriteLine(fullLine);
                }
            }

OK. Let's generalize the problem (see comments for the question): let us join all the properties which are:

  1. public and not static .
  2. Readable and Writable .
  3. Not indexers (what should we do with this[int, int] property?).
  4. Of specified types (eg string , int , decimal , double ) only (how can we save, a property of, say, IComparer<int> type?).

We can obtain such properties with a help of Reflection and Linq :

  using System.Linq;
  using System.Reflection;

  ...

  HashSet<Type> allowedTypes = new HashSet<Type>() {
    typeof(string), typeof(int), typeof(decimal), typeof(double)
  };

  var properties = typeof(Car)
    .GetProperties(BindingFlags.Instance | BindingFlags.Public)
    .Where(prop => prop.CanRead && prop.CanWrite)
    .Where(prop => !prop.GetIndexParameters().Any())
    .Where(prop => allowedTypes.Contains(prop.PropertyType))
 // .Where(prop => ...) // Add here more coditions if required
    .ToArray();

Now, having these properties we can save values into a file:

  using System.IO;
  using System.Linq;

  ...

  File.WriteAllLines(@"D:\WriteLines.txt", cars
    .Select(car => string.Join(",", properties
       .Select(property => property.GetValue(car)))));

Finally, you can combine these parts into a single routine :

  private static void SaveToFile<T>(IEnumerable<T> source, string fileName) {
    HashSet<Type> allowedTypes = new HashSet<Type>() {
      typeof(string), typeof(int), typeof(decimal), typeof(double)
    };

    var properties = typeof(T)
      .GetProperties(BindingFlags.Instance | BindingFlags.Public)
      .Where(prop => prop.CanRead && prop.CanWrite)
      .Where(prop => !prop.GetIndexParameters().Any())
      .Where(prop => allowedTypes.Contains(prop.PropertyType))
   // .Where(prop => ...) // Add here more coditions if required
      .ToArray();

    File.WriteAllLines(fileName, source
      .Select(item => string.Join(",", properties
        .Select(property => property.GetValue(item))))); 
  } 

Then use it:

  List<Car> cars = new List<Car>();

  ... 

  SaveToFile(Cars, @"D:\WriteLines.txt");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM