使用相同的方法发送各种类型的列表

时间:2016-03-03 13:28:07

标签: c# dynamic

这是我的代码:

var res = PrepareData(null);                //Prepare Data Returns a Tuple if two list assigned below.
List<Model.CameraSetting> lstCS = res.Item1; //List 1
List<ValidObjectsCameraSetting> lstVOCS = res.Item2; // List 2
if (isCSV)
{
       DataTable dtCameraSettings = ImportExportReportHelper.ConvertListToDataTable(lstCS);
       DataTable dtValidObjectCameraSetting = ImportExportReportHelper.ConvertListToDataTable(lstVOCS);
 }

这是我的

public static DataTable ConvertListToDataTable(List<dynamic> list){ //Do Something }

方法。我怎样才能在这里发送任何类型的对象并用它做事。 (我将做的是配置)。

我只想用同样的方法发送各种类型的列表。

4 个答案:

答案 0 :(得分:1)

也许你可以成功generic

public static DataTable ConvertListToDataTable<T>(List<T> list)
{
    Type listType = typeof(T);
    if(listType == typeof(CameraSetting))
    {
        //...
    }
    else if(listType == typeof(OtherThing))
    {
        //...
    }
    else  // if not everything is allowed
        throw new NotSupportedException(listType.ToString() + " is not supported in ConvertListToDataTable");
}

答案 1 :(得分:1)

使用非泛型和反射

如果要对列表中的项目使用反射(并且项目不是值类型),则没有特别的理由使用通用列表类型。我还建议使用接口而不是特定类型。例如:

public static DataTable ConvertListToDataTable(IEnumerable list){
    foreach (object item in list)
    {
        //Do Something
    }
}

如果您需要列表中的项目数,则可以使用ICollection代替IEnumerable

public static DataTable ConvertListToDataTable(ICollection list){
    if (list.Count > 0)
    {
        foreach (object item in list)
        {
            //Do Something
        }
    }
}

这两个接口都是由通用List<>类实现的,因此您可以将原始列表传递给函数,而不需要映射。

使用泛型

使用仿制药有好处,特别是类型安全。使用泛型时,在用于类型参数的类型之间通常存在某种共性。这是使用where类型约束强制执行的。

在这种特殊情况下,您的方法是将集合中的项目转换为数据表中的行。项类型之间的共性是它们可以转换为数据行。这可以使用接口定义,如下所示:

public interface IDataRowConvertible
{
}

public class CameraSettings : IDataRowConvertible
{
}

public static DataTable ConvertListToDataTable<T>(IEnumerable<T> list) where T : IDataRowConvertible
{
    // Do something
}

另一件需要考虑的事情是:为了做到正确,反思可能很棘手。您最终可能会遇到基于泛型反射的解决方案无法执行您希望的操作的情况。例如,假设您向其中一个您不希望包含在数据行中的类添加属性。使用界面可以解决这两个问题。

让我们改变界面:

public interface IDataRowConvertible
{
    void DefineColumns(DataColumnCollection columns);
    void WriteToRow(DataRow row);
}

您现在正在使项目负责定义数据表中的内容,并且您的转换功能变得非常通用:

public static DataTable ConvertListToDataTable<T>(ICollection<T> list) where T: IDataRowConvertible
{
    if (list.Count > 0)
    {
        var table = new DataTable();
        list.First().DefineColumns(table.Columns);
        foreach (var item in list)
        {
            var row = table.NewRow();
            item.WriteToRow(row);
            table.Rows.Add(row);
        }
        return table;
    }
    return null;
}

最大的缺点是现在所有的项目类都需要实现两种接口方法。但是,您可以创建基于反射的实用程序,以使其更易于实现:

public void DefineColumns(DataColumnCollection columns)
{
    ReflectionUtil.DefineColumns(this, columns);
}

public void WriteToRow(DataRow row)
{
    ReflectionUtil.WriteToRow(this, row);
}

答案 2 :(得分:0)

您可以为两个类创建一个互动界面,例如ICameraSettings,这样您就不需要在方法中投射对象,然后将列表更改为

List<ICameraSettings> lstCS;
List<ICameraSettings> lstVOCS;

或者您可以使用generics

public static DataTable ConvertListToDataTable<T>(List<T> list) where T:ICameraSettings

如果您不需要使用特定类型,则可以使用ICollection

 public static DataTable ConvertListToDataTable(ICollection list)

但是如果你在方法中对不同类型有不同的逻辑,那么你可能需要使用parameter overloading

答案 3 :(得分:0)

我会创建和接口然后两个类都实现它,这样做就可以列出那种类型的接口。

修改。有人回答我正在打字抱歉