DataTable to List<T> conversion
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)Activ开发者_Go百科ator.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. 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.
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;
}
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.
精彩评论