Milos
Milos

Reputation: 143

How to convert datarow to generic model class?

I have a lot of model classes that I fill in with data from API.
Structure of API data is DataRow.
For each class there is an implicit conversion from DataRow to model class. I have to write a set of functions for each model class. One of the functions, get from database, is common for all model classes so I decided to write function with generic type for this.

Here is an example of model class:

public class Person
{
    public long Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public static implicit operator Person(DataRow dataRow)
    {
        if (dataRow != null)
        {
            return new Person
            {
                Id = long.Parse((string)dataRow["Id"]),
                FirstName = (string)dataRow["FirstName"],
                LastName = (string)dataRow["LastName"]
            };
        };
        return null;
    }
}

example of class with generic type for casting, looks like this:

public class DefaultRepository<T>
{        
    public T CreateInstanceOfModelFromDataRow(DataRow dataRow)
    {
        T modelInstance = (T)Activator.CreateInstance(typeof(T));

        modelInstance = (T)dataRow;
        
        return modelInstance;
    }     
}

and code for testing looks like this:

// for testing I will create DataTable and DataRow and populate it fake data            
DataTable fakeTable = new DataTable();

fakeTable.Columns.Add("Id");
fakeTable.Columns.Add("FirstName");
fakeTable.Columns.Add("LastName");

DataRow fakeRow = fakeTable.NewRow();
        
fakeRow["Id"] = "1";
fakeRow["FirstName"] = "John";
fakeRow["LastName"] = "Doe";

// Cast DataRow to Pesron without error
Person fakePerson01 = (Person)fakeRow;

// Cant cast on this way create error while compiling
DefaultRepository<Person> defRepo = new DefaultRepository<Person>();
Person fakePerson02 = defRepo.CreateInstanceOfModelFromDataRow(fakeRow);

I get error while compiling "Cannot convert type 'System.Data.DataRow' to 'T'" at line modelInstance = (T)dataRow;

I try with (T)Convert.ChangeType(dataRow, typeof(T)); also but no luck.

Is it posible to do this conversion?

Upvotes: 1

Views: 1589

Answers (1)

Nikhil Patil
Nikhil Patil

Reputation: 2540

Since you are using generics, compiler does not know what type T is, hence you are getting the compile time error.

You will need to add constraint to your generic implementation -

public class DefaultRepository<T> where T : Person
{
        public T CreateInstanceOfModelFromDataRow(DataRow dataRow) 
        {
            T modelInstance = (T)Activator.CreateInstance(typeof(T));

            modelInstance = (T)dataRow;

            return modelInstance;
        }
}

Also you need not create instance through reflection. You can just cast dataRow to your class -

    public class DefaultRepository<T> where T : Person
    {
        public T CreateInstanceOfModelFromDataRow(DataRow dataRow) 
        {
            var modelInstance = (T)dataRow;

            return modelInstance;
        }
    }

Upvotes: 1

Related Questions