0

I am trying to achieve something like this in C#:

public class GenericModel
{
  public SetPropertiesFromDataRow(DataColumnCollection columns, DataRow row)
  {
    foreach(DataColumn column in columns)
    {
      this.SetProperty(column.ColumnName, row[column.ColumnName]);
    }
  }
}

DataTable students = ReadStudentsFromDatabase(); // This reads all the students from the database and returns a DataTable

var firstStudent = new GenericModel();
firstStudent.SetPropertiesFromDataRow(students.Columns, students.Rows[0]);

Is this possible to do in C# (since it is a static language)?
(Note that this example is somekind of psudocode.)

  • you might be better off getting a ORM like EntityFramework or NHibernate, it does all the hard work of figuring out how to do things like this with databases for you. – Scott Chamberlain Dec 20 '14 at 08:10
  • Maybe have a look here: http://stackoverflow.com/questions/619767/set-object-property-using-reflection – ZivS Dec 20 '14 at 08:11
  • @ScottChamberlain Unfortunately I can't, due to the project structure. I am working on a legacy project, and I can't use a new ORM. –  Dec 20 '14 at 08:13
  • Well if you can't use a ORM, perhaps a library like AutoMapper can take a lot of the load off of you writing your own reflection code. – Scott Chamberlain Dec 20 '14 at 08:14

4 Answers4

1

Here is example of using ExpandoObject

dynamic eo = new ExpandoObject();
var dic = eo as IDictionary<string, object>;
foreach (string propertyName in XXX)
{
    dic[propertyName] = propertyValue;
}
opewix
  • 4,993
  • 1
  • 20
  • 42
0

Absolutely, this is possible. C# has reflection system that lets you examine class structure and set class elements at runtime. For example, to set a property on this when all you have is a name in a string can be done as follows:

foreach(DataColumn column in columns) {
    PropertyInfo prop = GetType().GetProperty(column.Name);
    prop.SetValue(this, row[column.Name]);
}

This assumes several things:

  • Names of the DataColumn objects exactly match names of properties in your class, including capitalization
  • None of the DataColumns is missing in the type, i.e. if there is a column Xyz there must be a property Xyz in the class
  • Data types of objects you read from the data table are assignment-compatible with the types of their corresponding properties.

If any of these requirements is broken, there will be runtime errors. You can address them in code. For example, if you wish to make it work in situations when generic model might be missing some properties, add a null check on the prop variable, and skip the call to SetValue when you see prop ==null.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Is there (simple) way to create missing properties? –  Dec 20 '14 at 08:22
  • @TheCuriousGuy What do you mean by "create missing properties"? There is a type called `ExpandoObject` that lets you set missing properties as if you are setting values in a string-to-object dictionary. You can derive you class from it. Of course the properties that you create on the fly are pretty useless, unless you consume them in the same way that you create them, i.e. by name, because there is no code that accessing them as properties. – Sergey Kalinichenko Dec 20 '14 at 08:28
0

You can use Reflection to do this e.g.

objName.GetType().GetProperty("nameOfProperty").SetValue(objName, objValue, null)
varsha
  • 1,620
  • 1
  • 16
  • 29
0

Use dynamic variables for setting the dynamic property as below:

class Program{
   static void Main(string[] args)
    {
        dynamic x = new GenericModel();
        x.First = "Robert";
        x.Last = " Pasta";

        Console.Write(x.First + x.Last);
    }
  }

class GenericModel : DynamicObject
{
    Dictionary<string, object> _collection = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _collection.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _collection.Add(binder.Name, value);
        return true;
    }
}

Please refer to the link: MSDN

Lokesh
  • 129
  • 3