数据表到列表转换

发布于 2024-08-13 05:03:26 字数 503 浏览 3 评论 0原文

还有比下面更好的办法吗?

特别是,我想用其他东西替换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;
        }

Is there any better way than the following?

Particularly, I want to replace Activator with something else.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

余罪 2024-08-20 05:03:26

我要提到的第一件事是您可能不需要列表。可能性是,一个 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 类型的函数。该函数可能使用Activator,但并非必须如此。它可能只使用普通的构造函数并设置一些属性。

The first thing I want to mention is that you probably don't need a list. Odds are, an IEnumerable is enough. Even if you do need a list, it's trivial to convert an IEnumerable to a list.

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. That function might use Activator, but it doesn't have to. It might just use a normal constructor and set a few properties.

猫九 2024-08-20 05:03:26

我真的没有看到任何改进此代码的方法 - 为什么要避免 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;
}

I don't really see any way to improve this code - why do you want to avoid 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;
}
放赐 2024-08-20 05:03:26

我要在安德鲁的答案中添加的一件事是,如果您走这条路,您可以通过使用 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);
    }
    ...
}

我之所以说“有点”,是因为 C# 实际上只是在编译时将其编译为 Activator.CreateInstance 调用。但看起来干净多了。

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.

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. But it looks much cleaner.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文