0

I have all kind of classes that represents entities, for example:

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public bool IsSystemManager { get; set; }
    public bool IsSystemAdmin { get; set; }

    public Person() { }

    public Person(DataRow row)
    {
        PersonID = (int)row["person_id"];
        PersonName = row["person_name"] as string;
        IsSystemManager = (bool)row["is_manager"];
        IsSystemAdmin = (bool)row["is_admin"];
    }
}

And I want to have an extension to DataTable that turns it into a list of a class object, like this:

public static List<T> ToObjectList<T>(this DataTable table) where T : new(DataRow dr) //this is a compilation error
{
    List<T> lst = new List<T>();

    foreach (DataRow row in table.Rows)
        lst.Add(new T(row));

    return lst;
}

But I can't have the constraint for contstructor with DataRow as a parameter.

Is there any way to have an extension method like this?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Liran Friedman
  • 4,027
  • 13
  • 53
  • 96
  • @haim770 he's returning a `List` not a `List` and T is suppossed to take a DAtaRow in the constructor – Rune FS Jul 14 '15 at 08:11
  • 1
    the problem set aside, i would highly recommend not passing a datarow to the ctor but exploding the required parameters (having one for every member the ctor sets) you could pass a datarow which makes the ctor call fail easily – nozzleman Jul 14 '15 at 08:17

3 Answers3

4

No, you can't require a constructor with parameters. About the best you can do here would be to require a lambda:

public static List<T> ToObjectList<T>(this DataTable table,Func<DataRow,T> convert)
{
    List<T> lst = new List<T>();

    foreach (DataRow row in table.Rows)
        lst.Add(convert(row));

    return lst;
}

Usage:

var list = myDataTable.ToObjectList(dr=>new Person(dr));

Further reading:

Constraints on type parameters

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
0

You cannot specify type of new constraint for generic types. What you can do however is to create two different constraints as follows:

public static List<T> ToObjectList<T>(this DataTable table) where T : DataRow where T : new()

Here you specify that your parameter T must be of type DataTable (or derived from DataTable) and that new instance of it l be created inside your method

Fabjan
  • 13,506
  • 4
  • 25
  • 52
  • as far as i am understanding, he does not want to return `List` but `List`. – nozzleman Jul 14 '15 at 08:13
  • TS wanted to added a constraint that DataRow must be accepted as constructor parameter new (Datarow) and i just pointed that this is not possible. – Fabjan Jul 14 '15 at 08:22
0

Nope, you can only require an empty constructor with generic constraints.

An alternative pattern would be to require a Load method:

public interface ILoadable
{
    void Load(DataRow row);
}

public class Person : ILoadable
{
    ...

    public Person() { }

    public void Load(DataRow row)
    {
        PersonID = (int)row["person_id"];
        ...
    }
}

Then you can declare your method as follows:

public static List<T> ToObjectList<T>(this DataTable table) where T : ILoadable, new()
Heinzi
  • 167,459
  • 57
  • 363
  • 519