#c# #dynamic #reflection
#c# #динамический #отражение
Вопрос:
Пытаюсь написать утилиту сопоставления данных, управляемую данными. Но мне нужно иметь возможность инициализировать объекты (строки в списке), ссылающиеся на имена свойств (столбцов) в качестве переменных.
Так, например, вместо этого:
var p = new person {name = "Joe", age = 10}
могу ли я сделать что-то вроде…
string prop1 = "name", prop2 = "age";
var p = new person {[prop1] = "Joe", [prop2] = 10}
… или мы могли бы как-то обработать свойства как упорядоченную коллекцию, например
var p = new person {prop[1] = "Joe", prop[2] = 10}
… или неявно упорядочить их, просто отбросив имена свойств, предполагая, что свойства будут подразумеваться…
var p = new person {"Joe", 10}
Комментарии:
1. Разве вы не должны смотреть на отражение? Инициализаторы объектов в любом случае являются просто синтаксическим сахаром для установщиков. Они вообще не влияют на то, как вы работаете с объектом
2. Может быть, словарь
string
иobject
был бы лучшей идеей для источника?3. @KarlRKaiser что ты на самом деле пытаешься сделать? Какова реальная проблема, которую вы пытаетесь решить? Очевидно, вам нужен какой-то способ динамической настройки свойств, но почему? Разве это не было бы решено, например, с помощью AutoMapper или аналогичного инструмента?
4. … Чего бы это ни стоило — я просто не могу использовать литеральные имена свойств, но мне нужно как-то сопоставить строковые значения со свойствами, и я не против написать итерационный метод или что-то еще, чтобы сделать это.
5. …Я пытаюсь делать то, что я делал десятилетиями — абстрагировать отображение данных, потому что поддерживать сопоставления в табличной форме проще, чем в коде. В такой среде, как FoxPro, можно «макро» что угодно, что обеспечивает гибкость для выполнения подобных действий по желанию, но я застрял с правилами ввода в c #..
Ответ №1:
Нет, вы не можете этого сделать. Единственное, что вы можете сделать для достижения этой цели, — использовать отражение для установки свойств:
var p = new person();
var nameProp = typeof(person).GetProperty('name');
nameProp.SetValue(p, "Joe");
чтобы иметь неявный порядок свойств, вы можете объявить конструктор:
class person
{
public string name {get;set;}
//...
person(string name, int age){
this.name = name;
//...
}
и вызовите
new person("Joe",44);
Комментарии:
1. …итак, typeof(person) . getProperty(‘name’) фактически является ссылкой на само свойство, которое можно использовать для присвоения значения? Похоже, это сработает.
2. Своего рода; Это объект, который разрешает доступ ко всем метаданным, касающимся свойства, и позволяет устанавливать его значение. Тем не менее, я бы посоветовал не использовать отражение в любом проекте. Вы должны прочитать об этом больше, прежде чем начать его использовать.
3. Если я могу установить значение свойства, ссылаясь на него через метаданные или как оцениваемое свойство / datum, а не его буквальное имя, я буду в порядке. Я не знаю, назвал бы я использование «тяжелым», но сопоставление данных всегда лучше всего работало для меня в системе, основанной на правилах, основанной на данных, из-за гибкости, которую она предлагает при настройке или изменении правил сопоставления, не требуя также перекомпиляции и развертывания кода. Затем, если это сработает, я вернусь и спрошу, как ссылаться на ОБЪЕКТЫ в качестве метаданных 😉
Ответ №2:
Вы можете использовать person.GetType().GetProperty(prop1).SetValue(person,"Joe");
, конечно, вам нужно добавить nullchecking на GetProperty
.
Комментарии:
1. Другими словами, используйте отражение.
2. Спасибо, это было именно то, что я искал. Можно также спросить: есть ли способ также ссылаться на объект как на динамическое имя, чтобы все выражение присваивания не имело буквального имени объекта или свойства.
3. Вы можете использовать
Type.GetType("your.full.namespace.class")
Ответ №3:
Самым близким было бы использование отражения:
var person = new Person();
person.GetType().GetProperty("Name").SetValue(person, "Joe");