Отражение: как получить объект класса через PropertyInfo

У меня 2 класса. Класс A содержит некоторые объекты класса B, называемые Field01, Field02, ... Класс A также имеет список элементов класса B.

Я знаю название элементов ClassB и хочу заполнить элементы ClassB значениями из списка.

Пример кода:

public class ClassA
{
    public ClassB Field01 {get;set;}
    public ClassB Field02 {get;set;}
    //...

    List<ClassB> myItems;

    public void FillItems()
    {
        foreach(var item in MyItems)
        {
           // what I want in hardcode:
           Field01.ValueA = MyItems[0].ValueA;
           Field01.ValueB = MyItems[0].ValueB;
           Field02.ValueA = MyItems[1].ValueA;
           // ...
        }
    }
}

public class ClassB 
{
    public string ValueA {get;set;}
    public string ValueB {get;set;}
}

В моем случае у меня будет переменная подсчета, которая создаст имена Field01, Field02, Field03,... в зависимости от того, сколько элементов находится в моем списке (в ClassA всегда достаточно полей ClassB для заполнения)

Я знаю, что могу получить PropertyInfo своих элементов ClassB по имени, но я не знаю вас, я могу получить доступ к атрибутам ClassB ValueA и ValueB

// If ClassB was just a string or object this would work
Type myType = typeof(ClassA);
PropertyInfo myPropInfo = myType.GetProperty("Field01");
myPropInfo.SetValue(this, "Hello", null);

person Aiko West    schedule 15.01.2020    source источник
comment
Вы написали дополнительный цикл foreach в своем примере кода?   -  person Sweeper    schedule 15.01.2020
comment
что ты имеешь в виду под дополнительным   -  person Aiko West    schedule 15.01.2020
comment
stackoverflow.com/questions/34628996/   -  person Salah Akbari    schedule 15.01.2020
comment
@K.Dexter Цикл foreach в примере кода кажется избыточным, не так ли? Конечно, вы не хотите устанавливать каждое поле много раз с одним и тем же значением? Вы все равно не используете item.   -  person Sweeper    schedule 15.01.2020
comment
@Sweeper ах, теперь я понимаю, что вы имеете в виду ... код жесткого кода принадлежит выше foreach ... в цикле foreach генерируются имена полей, и каждый элемент адресует одно поле :) Я проверяю ваш ответ прямо сейчас   -  person Aiko West    schedule 15.01.2020
comment
Если подумать: это довольно странная вещь, которую вы делаете. Что ты пытаешься сделать? Вы пытаетесь создать глубокие копии ClassB из списка? Почему у вас нумерованные свойства? Почему не другой список?   -  person Sweeper    schedule 15.01.2020
comment
в настоящее время это временное решение. Я получаю заполненный список от своей службы, но для сопоставления этих элементов с сеткой данных мне нужны заполненные поля.   -  person Aiko West    schedule 15.01.2020


Ответы (1)


Поскольку вы знаете, что тип объявления свойств — ClassB, вы можете получить PropertyInfo из ValueA и ValueB. Затем вам нужно получить значение FieldXX (не задавать его!) и установить ValueA и ValueB.

Мы будем иметь дело с несколькими объектами Type, PropertyInfo и object, поэтому вы должны правильно назвать свои переменные, а не только myPropInfo или myType.

for (int i = 0 ; i < MyItems.Count ; i++) {
    var classAType = typeof(ClassA);
    var classBType = typeof(ClassB);
    var fieldInfo = classAType.GetProperty("Field" + $"{i}".PadLeft(2, '0'));
    var fieldValue = fieldInfo.GetValue(this);
    var valueAInfo = classBType.GetProperty(nameof(ClassB.ValueA));
    var valueBInfo = classBType.GetProperty(nameof(ClassB.ValueB));
    valueAInfo.SetValue(fieldValue, valueAInfo.GetValue(MyItems[i]));
    valueBInfo.SetValue(fieldValue, valueBInfo.GetValue(MyItems[i]));
}
person Sweeper    schedule 15.01.2020
comment
хорошо, пока это работает :), но только если я создаю экземпляры своих объектов ClassB в ClassA public ClassB Field01 {get;set;} = new ClassB(); - person Aiko West; 15.01.2020
comment
@K.Dexter Конечно, вам нужно их создать! В противном случае вы получите NRE. - person Sweeper; 15.01.2020
comment
есть ли способ создать их в цикле? - person Aiko West; 15.01.2020
comment
@K.Dexter Вместо var fieldValue = fieldInfo.GetValue(this); вы пишете var fieldValue = new ClassB(); и fieldInfo.SetValue(this, fieldValue); - person Sweeper; 15.01.2020