Sirwan Afifi
Sirwan Afifi

Reputation: 10824

Casting PropertyDescriptor to List<Tuple<string, string>>

I have following class:

public class Cmp
{
    public List<Tuple<string, string>> Hdd { get; set; }
    public string Cpu { get; set; }
    public string MonitorModel { get; set; }
    public List<Tuple<string, string>> OpticDriver { get; set; }
}

I am also using this code to convert List<Cmp> to CSV:

public static void WriteToCsv<T>(IEnumerable<T> data)
{
    var strBuilder = new StringBuilder();
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
    foreach (PropertyDescriptor prop in props)
    {
        strBuilder.Append(prop.DisplayName); // header
        strBuilder.Append(",");
    }
    strBuilder.AppendLine();
    foreach (T item in data)
    {
        foreach (PropertyDescriptor prop in props)
        {
            strBuilder.Append(prop.Converter.ConvertToString(
                prop.GetValue(item)));
            strBuilder.Append(",");
        }
        strBuilder.AppendLine();
    }

    File.WriteAllText(@"C:\list.csv", strBuilder.ToString());
}

Just wondering How can I iterator over Hdd and OpticDriver properties inside WriteToCsv<T>. Currently the result is like this:

 Hdd            Cpu     MonitorModel    OpticDriver
(Collection)    CPU1    Monitor1        (Collection)
(Collection)    CPU2    Monitor2        (Collection)
(Collection)    CPU3    Monitor3        (Collection)

I want it to be like this:

 Hdd            Cpu     MonitorModel    OpticDriver
Hdd1-Hdd2       CPU1    Monitor1        Disk1-Disk2
Hdd1-Hdd2       CPU2    Monitor2        Disk1-Disk2
Hdd1-Hdd2       CPU3    Monitor3        Disk1-Disk2

Upvotes: 1

Views: 460

Answers (2)

Lajos Arpad
Lajos Arpad

Reputation: 76787

You might have more Hdd and OpticDriver items for the same Cpu and MonitorModel, respectively, therefore you will need three cycles:

  • the first will iterate your list of Cmp
  • the second will iterate the Hdd items of a given Cmp item
  • the third will iterate the OpticDriver items of a given Cmp item with a given Hdd

If you want to keep WriteToCsv generic, then check for the type of prop and if it is some kind of set, then you will need to implement an inner cycle for it. You can achieve this both iteratively or recursively, but the former is recommended. You will just make sure you mine all the multi-dimensional tuples you need. I recommend the usage of an array where you store as many iterators as you like and when an iterator finishes its set, set it to the first item of the given set and go to the next item of the previous set in the array, until the first iterator finishes its job. If this answer is unclear, let me know, I will give you the algorithm then.

Upvotes: 1

Mariusz Jamro
Mariusz Jamro

Reputation: 31663

Solution 1

Cast the value to List<Tuple<string,string>> and handle it differently than other properties

foreach (PropertyDescriptor prop in props)
{
    var value = prop.GetValue(item);
    if(value is List<Tuple<string, string>> tupleList)
    {
        string tupleString = ConvertTupleListToString(tupleList);
        strBuilder.Append(tupleString);
    }
    else
    {
        strBuilder.Append(prop.Converter.ConvertToString(value));
    }
    strBuilder.Append(",");
}

Solution 2

Instead of using generic List<Tuple<string,string>> consider using your own List-like type with custom ToString() implementation which will return whatever you want.

public class HddInfoList : List<Tuple<string, string>>
{
    public HddInfoList(IEnumerable<Tuple<string, string>> collection) : base(collection)
    {

    }

    public override string ToString()
    {
        //For example return first items of tuple separated by '-'
        return string.Join("-", this.Select(m => m.Item1));
    }
}

Upvotes: 1

Related Questions