C # цикл foreach через коллекцию неизвестного типа - PullRequest
0 голосов
/ 20 июня 2019

У меня есть универсальный метод, который можно вызывать с двумя различными типами объектов, TypeA или TypeB.TypeA и TypeB - по существу идентичные классы, за исключением только имени.Я пытаюсь определить, как избежать дублирования кода цикла Foreach для каждого типа объекта.Это возможно ?Благодарю.

public class TypeA
{
    public string Name { get; set; }
    public string Department { get; set; }
    public string Total { get; set; }
}

public class TypeB
{
    public string Name { get; set; }
    public string Department { get; set; }
    public string Total { get; set; }
}


 private CsvExport GenerateExport<T>(IEnumerable<T> scores)
 {
    CsvExport export = new CsvExport();

    List<TypeA> aList = null;
    List<TypeB> bList = null;

    Type type = scores.GetType();

    if (type.FullName.Contains("TypeA"))
    {
        aList = scores as List<ObjectaModel>;
    }
    else if (type.FullName.Contains("TypeB"))
    {
        bList = scores as List<ObjectbModel>;
    }

    foreach (var dt in aList)
    {
        export.AddRow();
        export["Name"] = dt.Name;
        export["Department"] = dt.Department;
        export["Total "] = dt.Total;
     };

    return export;
}

1 Ответ

2 голосов
/ 20 июня 2019

В этом конкретном случае я настоятельно рекомендую вам делегировать тяжелую работу в библиотеку CsvHelper , которую вы также можете получить из Nuget и которая используется следующим образом. ..

 public void ExportToCsv<T>(string filename, ImmutableArray<T> objects)
 {
    using (var writer = File.CreateText(filename))
    {
        var csv = new CsvWriter(writer);
        csv.WriteRecords(objects);
    }
  }

Более общий ответ на ваш вопрос заключается в том, что вы должны либо оба класса наследовать от общего класса или интерфейса, либо вам придется использовать отражение , чтобы найти значения именованных свойств.

Использование общего интерфейса ...

public interface IScore
{
  int HiScore {get;}
}

public class ScrabbleScore : IScore
{
  public int HiScore {get;set;}
}


public class PacManScore : IScore
{
   public int HiScore {get;set;}
}

public void Export<T>(IEnumerable<T> scores) where T: IScore
{
  foreach(var s in scores)
  {
     CvsExport["Hi score"]= s.HiScore;
  }
}

Использование отражения ...

        var CsvExport = new Dictionary<string,string>();
        foreach(var o in scores)
        {   
            //note that checking the type for each object enables you to have heterogenous lists if you want
            var objectType= o.GetType();
            foreach(var p in objectType.GetProperties())
            {
               var propertyName = p.Name;
               CsvExport[propertyName] = p.GetValue(o).ToString();
            }
        }

Я бы отнес решение к отражению как наименее предпочтительное из трех.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...