在运行时设置类的属性

本文关键字:属性 设置 运行时 | 更新日期: 2023-09-27 18:34:50

我正在尝试在 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]);

这在 C# 中是否可以做到(因为它是一种静态语言(?
(请注意,此示例是某种伪代码。

在运行时设置类的属性

以下是使用 ExpandoObject 的示例

dynamic eo = new ExpandoObject();
var dic = eo as IDictionary<string, object>;
foreach (string propertyName in XXX)
{
    dic[propertyName] = propertyValue;
}

当然,这是可能的。C# 具有反射系统,可让您在运行时检查类结构并设置类元素。例如,当您在string中只有一个名称时,要在this上设置属性,可以按以下步骤完成:

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

这假设了几件事:

  • DataColumn对象的名称与类中的属性名称(包括大小写(完全匹配
  • 类型中没有缺少任何DataColumn s,即如果存在列Xyz则类中必须有一个属性Xyz
  • 从数据表中读取的对象数据类型与其相应属性的类型赋值兼容。

如果这些要求中的任何一个被破坏,就会出现运行时错误。您可以在代码中解决它们。例如,如果您希望使其在通用模型可能缺少某些属性的情况下工作,请对prop变量添加null检查,并在看到prop ==null时跳过对SetValue的调用。

您可以使用反射来执行此操作,例如

objName.GetType().GetProperty("nameOfProperty").SetValue(objName, objValue, null)

使用动态变量设置动态属性,如下所示:

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;
    }
}

请参考链接:MSDN