简体   繁体   English

C#foreach循环通过未知类型的集合

[英]C# foreach loop thru collection of unknown type

I have a generic method that can be called with 2 different object types, TypeA or TypeB. 我有一个可以用2种不同的对象类型TypeA或TypeB调用的通用方法。 TypeA and TypeB are essentially identical classes except in name only. TypeA和TypeB本质上是相同的类,只是名称不同。 I am trying to determine how to prevent from having to duplicate the Foreach loop code for each object type. 我试图确定如何避免必须为每种对象类型重复Foreach循环代码。 Is this possible ? 这可能吗 ? thanks. 谢谢。

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;
}

In this particular case I strongly suggest you delegate the hard work to the CsvHelper library which you can also obtain from Nuget and is used like this... 在这种特殊情况下,我强烈建议您将辛苦的工作委托给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);
    }
  }

The more general answer to your question is that you must either have both classes inherit from a common class or interface or you would have to use reflection to look for an obtain the values of the named properties. 对于您的问题的更一般的答案是,您必须使两个类都从同一个类或接口继承,否则您将不得不使用反射来查找获取命名属性的值。

Using a common interface ... 使用通用界面 ...

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;
  }
}

Using reflection ... 使用反射 ...

        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();
            }
        }

I would treat the reflection solution as the least favoured of the three. 我将反射解决方案视为三者中最不受欢迎的一种。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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