инициализация объекта c # — возможно ссылаться на свойства по нелитеральному имени?

#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");