2

以下より良い方法はありますか?

特に、他のものに交換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;
        }
4

3 に答える 3

6

私が最初に言及したいのは、おそらくリストは必要ないということです。たぶん、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を使用する場合がありますが、使用する必要はありません。通常のコンストラクターを使用して、いくつかのプロパティを設定するだけかもしれません。

于 2009-12-06T00:27:04.767 に答える
2

このコードを改善する方法が本当にわかりません-なぜ避けたいのActivatorですか?

検討できるオプションの1つは、次のようなインターフェイスを作成することです。

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;
}
于 2009-12-06T00:25:50.497 に答える
0

アンドリューの答えに追加したいことの1つは、そのルートに進むと、ジェネリックメソッドを 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 呼び出しにコンパイルするだけだからです。しかし、それははるかにきれいに見えます。

于 2009-12-06T00:32:27.613 に答える