Mark
Mark

Reputation: 315

DataRow Field Cast From Variable

Is it possible to cast a type from a variable? I'm extracting data from a spreadsheet into a class, but because some columns are strings, and others DateTime, I really want a do-all command, that I don't need to map everything manually.

What I have so far:

foreach (PropertyInfo pinfo in asset.GetType().GetProperties())
{
    string columnType = (from DataColumn column in data.Columns where column.ColumnName == pinfo.Name select column).First().DataType.ToString();
    pinfo.SetValue(asset, row.Field<columnType>(pinfo.Name));
}

At the moment, it doesn't like row.Field<columnType>(), because it's not a real type.

Is it possible to do something like the above, where I'm getting the type contained in a column, and casting this to retrieve the data for that column? I'm in this situation, as I want to retrieve anything using the following statement, regardless of whether it's a string, int or DateTime.

var foo = row.Field<string>("Column Name");

Is there any generic command I can use? Thanks

Upvotes: 0

Views: 1551

Answers (1)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236328

PropertyInfo.SetValue accepts value as object. If your DataTable has column of appropriate type, then just get column value with row[columnName] which also will be returned as object, and use it to set property value:

foreach (PropertyInfo pinfo in asset.GetType().GetProperties())
{
     pinfo.SetValue(asset, row[pinfo.Name]);
}

Sample: consider you have class

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

And you have DataTable which has columns with appropriate types:

DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Rows.Add(1, "Bob");
dt.Rows.Add(2, "John");

Then filling user from DataTable will look like:

var user = new User();
var row = dt.Rows[0];

foreach (PropertyInfo pinfo in user.GetType().GetProperties())
    pinfo.SetValue(user, row[pinfo.Name]);

NOTE: You can skip properties which don't have appropriate type, also you can handle case when there is no column with property name:

foreach (PropertyInfo pinfo in user.GetType().GetProperties())
{
    if (!dt.Columns.Contains(pinfo.Name) || 
         dt.Columns[pinfo.Name].DataType != pinfo.PropertyType)
        continue;

    pinfo.SetValue(user, row[pinfo.Name]);
}

Upvotes: 2

Related Questions