简体   繁体   English

DataTable to List <T> 转变

[英]DataTable to List<T> conversion

Is there any better way than the following? 有没有比以下更好的方法?

Particularly, I want to replace Activator with something else. 特别是,我想用其他东西取代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;
        }

The first thing I want to mention is that you probably don't need a list. 我想提到的第一件事是你可能不需要列表。 Odds are, an IEnumerable is enough. 赔率是,IEnumerable足够了。 Even if you do need a list, it's trivial to convert an IEnumerable to a list. 即使你确实需要一个列表,将IEnumerable转换为列表也是微不足道的。

With that in mind, this code is a nice generic way to accomplish it: 考虑到这一点,这段代码是实现它的一种很好的通用方法:

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

Hopefully you can see how re-usable this is. 希望你能看到它的可重用性。 All you need to do is supply a function that knows how to convert an individual DataRow into your T type. 您需要做的就是提供一个知道如何将单个DataRow转换为T类型的函数。 That function might use Activator, but it doesn't have to. 该函数可能使用Activator,但它不必。 It might just use a normal constructor and set a few properties. 它可能只使用普通的构造函数并设置一些属性。

I don't really see any way to improve this code - why do you want to avoid Activator ? 我真的没有办法改进这段代码 - 你为什么要避免使用Activator

One option you could explore would be to create some sort of interface like this: 您可以探索的一个选项是创建某种类似的界面:

interface IFoo
{
    void Initialize(DataRow dr);
}

And then implement this interface on any type that gets passed to this method. 然后在传递给此方法的任何类型上实现此接口。 Then you would constrain your generic type parameter like this: 然后你会限制你的泛型类型参数,如下所示:

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

Then change the implementation of your method like this: 然后像这样更改方法的实现:

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

One thing I'd add to Andrew's answer is if you go that route you can (sorta) avoid the Activator class by constraining the generic method with a new() constraint. 我要添加到Andrew的答案中的一件事是,如果你走这条路,你可以通过用new()约束约束泛型方法来避免Activator类。

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

The reason I say "sorta" is because C# actually just compiles that into an Activator.CreateInstance call at compile-time anyway. 我说“sorta”的原因是因为C#实际上只是在编译时将其编译成Activator.CreateInstance调用。 But it looks much cleaner. 但它看起来更干净。

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

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