DataTable to List <T>преобразование - PullRequest
2 голосов
/ 06 декабря 2009

Есть ли лучший способ, чем следующий?

В частности, я хочу заменить Activator чем-то другим.

public static List<T> ToList<T>(DataTable dt)
        {
            Type type = typeof(T);

            List<T> list = new List<T>();

            foreach (DataRow dr in dt.Rows)
            {
                object[] args = new object[1];

                args[0] = dr;

                list.Add((T)Activator.CreateInstance(type, args));
            }

            return list;
        }

Ответы [ 3 ]

6 голосов
/ 06 декабря 2009

Первое, что я хочу упомянуть, это то, что вам, вероятно, не нужен список. Скорее всего, IEnumerable достаточно. Даже если вам нужен список, легко преобразовать IEnumerable в список.

Имея это в виду, этот код является хорошим общим способом сделать это:

public static IEnumerable<T> ToEnumerable<T>(DataTable dt, Func<DataRow, T> translator)
{
    foreach(DataRow dr in dt.Rows)
    {
       yield return translator(dr);
    }
}

Надеюсь, вы увидите, насколько это многоразово. Все, что вам нужно сделать, это предоставить функцию, которая знает, как преобразовать отдельный DataRow в ваш тип T. Эта функция может использовать активатор, но это не обязательно. Он может просто использовать обычный конструктор и установить несколько свойств.

2 голосов
/ 06 декабря 2009

Я не вижу способа улучшить этот код - почему вы хотите избежать Activator?

Один из вариантов, который вы могли бы изучить, - это создать некий интерфейс, подобный следующему:

interface IFoo
{
    void Initialize(DataRow dr);
}

И затем реализуйте этот интерфейс для любого типа, который передается этому методу. Тогда вы ограничите свой параметр общего типа следующим образом:

public static List<T> ToList<T>(DataTable dt)
    where T : IFoo, new()

Затем измените реализацию вашего метода следующим образом:

public static List<T> ToList<T>(DataTable dt)
    where T : IFoo, new()
{
    List<T> list = new List<T>();

    foreach (DataRow dr in dt.Rows)
    {
        T t = new T();
        t.Initialize(dr);
        list.Add(t);
    }
    return list;
}
0 голосов
/ 06 декабря 2009

Одна вещь, которую я бы добавил к ответу Эндрю, состоит в том, что если вы пойдете по этому пути, вы можете (как бы) избежать класса Activator, ограничив универсальный метод с помощью ограничения new ().

public static List<T> ToList<T>(DataTable dt)
    where T : IFoo, new()
{
    ...
    foreach ( ... ) {
       var foo = new T();
       foo.Initialize(dataRow);
       list.Add(foo);
    }
    ...
}

Причина, по которой я говорю "сортировка", заключается в том, что C # на самом деле просто компилирует это в вызов Activator.CreateInstance во время компиляции в любом случае. Но выглядит намного чище.

...