Используя отражение в C# для получения свойств вложенного объекта

Учитывая следующие объекты:

public class Customer {
    public String Name { get; set; }
    public String Address { get; set; }
}

public class Invoice {
    public String ID { get; set; }
    public DateTime Date { get; set; }
    public Customer BillTo { get; set; }
}

Я хотел бы использовать отражение для прохождения через Invoice добираться Name свойство a Customer. Вот то, что я после, предполагая, что этот код работал бы:

Invoice inv = GetDesiredInvoice();  // magic method to get an invoice
PropertyInfo info = inv.GetType().GetProperty("BillTo.Address");
Object val = info.GetValue(inv, null);

Конечно, это перестало работать начиная с "BillTo. Адрес" не является допустимым свойством Invoice класс.

Так, я пытался писать метод, чтобы разделить строку на части на периоде и обойти объекты, ища окончательное значение, которым я интересовался. Это работает хорошо, но я не совсем доволен им:

public Object GetPropValue(String name, Object obj) {
    foreach (String part in name.Split('.')) {
        if (obj == null) { return null; }

        Type type = obj.GetType();
        PropertyInfo info = type.GetProperty(part);
        if (info == null) { return null; }

        obj = info.GetValue(obj, null);
    }
    return obj;
}

Какие-либо идеи о том, как улучшить этот метод или лучший способ решить эту проблему?

РЕДАКТИРОВАНИЕ после регистрации, я видел несколько связанных сообщений... Кажется, нет ответа, который конкретно обращается к этому вопросу, как бы то ни было. Кроме того, я все еще хотел бы обратную связь на своей реализации.

69
задан jheddings 23 December 2009 в 19:10
поделиться

5 ответов

Я на самом деле думаю, что ваша логика в порядке. Лично я бы, вероятно, изменил ее так, чтобы вы передали объект в качестве первого параметра (что более соответствует PropertyInfo.GetValue, так что менее удивительно).

Я бы также, вероятно, назвал ее более похожей на GetNestedPropertyValue, чтобы было очевидно, что она ищет в стеке свойств.

.
12
ответ дан 24 November 2019 в 13:56
поделиться

Вы не объясняете источник вашего "дискомфорта", но ваш код, по сути, кажется мне звучным.

Единственное, что я бы поставил под сомнение - это обработка ошибок. Вы возвращаете ноль, если код пытается пройти через нулевую ссылку или если имя свойства не существует. Это скрывает ошибки: сложно узнать, вернул ли он ноль, потому что нет клиента BillTo, или вы неправильно написали "BilTo.Address"... или потому что есть клиент BillTo, и его адрес равен нулю! Я бы позволил этому методу упасть и сгореть в этих случаях - просто дайте исключению уйти (или, может быть, обернуть его в более дружелюбное).

.
6
ответ дан 24 November 2019 в 13:56
поделиться

Вы должны получить доступ к АКТУАЛЬНОМУ объекту, на котором нужно использовать отражение. Вот что я имею в виду:

Вместо этого:

Invoice inv = GetDesiredInvoice();  // magic method to get an invoice
PropertyInfo info = inv.GetType().GetProperty("BillTo.Address");
Object val = info.GetValue(inv, null);

Сделайте это (отредактировано на основе комментария):

Invoice inv = GetDesiredInvoice();  // magic method to get an invoice
PropertyInfo info = inv.GetType().GetProperty("BillTo");
Customer cust = (Customer)info.GetValue(inv, null);

PropertyInfo info2 = cust.GetType().GetProperty("Address");
Object val = info2.GetValue(cust, null);

Посмотрите на этот пост для дополнительной информации: Использование отражения для установки свойства объекта

10
ответ дан 24 November 2019 в 13:56
поделиться

Попробуйте inv.GetType().GetProperty("BillTo+Address");

-7
ответ дан 24 November 2019 в 13:56
поделиться
   if (info == null) { /* throw exception instead*/ } 

Я бы на самом деле сделал исключение, если бы они запросили несуществующее свойство. Как вы его закодировали, если я вызову GetPropValue и оно вернёт нуль, я не знаю, означает ли это, что свойства не существовало, или свойство действительно существовало, но его значение было нулевым

.
1
ответ дан 24 November 2019 в 13:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: