2014-12-20 5 views
0

Я пытаюсь добиться чего-то вроде этого в 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# (так как это статический язык)?
(Обратите внимание, что этот пример является чем-то вроде psudocode.)

+0

вы могли бы быть лучше получить ОРМ как EntityFramework или NHibernate, это делает всю тяжелую работу по выяснению, как делать подобные вещи с базами данных для вас. –

+0

Возможно, посмотрите здесь: http://stackoverflow.com/questions/619767/set-object-property-using-reflection – ZivS

+0

@ScottChamberlain К сожалению, я не могу, из-за структуры проекта. Я работаю над старым проектом, и я не могу использовать новый ORM. –

ответ

0

Абсолютно, это возможно. C# имеет систему отражения, которая позволяет вам изучать структуру классов и задавать элементы класса во время выполнения. Например, чтобы установить свойство на this, когда все у вас есть имя в string может быть сделано следующим образом:

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

Это предполагает несколько вещей:

  • Названия DataColumn объектов точно соответствуют имена объектов в вашем классе, включая капитализацию
  • В этом типе отсутствует ни одна из DataColumn s, то есть, если есть столбец Xyz, должно быть имущество Xyz в классе
  • Типы данных, которые вы читаете из таблицы данных, совместимы с типами соответствующих им свойств.

Если какое-либо из этих требований нарушено, будут ошибки времени выполнения. Вы можете обращаться к ним в коде. Например, если вы хотите заставить его работать в ситуациях, когда общая модель может отсутствовать в некоторых свойствах, добавьте null в переменной prop и пропустите звонок до SetValue, когда вы увидите prop ==null.

+0

Работает ли это, если свойство «GenericModel» не имеет свойства? –

+0

Есть ли (простой) способ создания недостающих свойств? –

+0

@ TheCuriousGuy Что значит «создавать недостающие свойства»? Существует тип под названием «ExpandoObject», который позволяет вам устанавливать отсутствующие свойства так же, как если бы вы задавали значения в словаре «строка-объект». Вы можете получить от вас класс. Конечно, свойства, которые вы создаете на лету, довольно бесполезны, если вы не потребляете их так же, как вы их создаете, т. Е. По имени, потому что нет кода, который обращается к ним как к свойствам. – dasblinkenlight

1

Вот пример использования ExpandoObject

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

Вы можете использовать Reflection, чтобы сделать это, например,

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

Использование динамических переменных для настройки динамического свойства, как показано ниже:

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

Смежные вопросы