Я некоторое время искал и играл с GetType(), но я продолжаю получать имя столбца (которое у меня уже есть), а не значение.

Я пытаюсь создать файл csv из результатов метода (вызов хранимой процедуры) в контексте данных.

Я в порядке, чтобы выяснить, как динамически получить result.some_column_name из набора результатов.

using (SomeDataContext ctx = new SomeDataContext())
        {
        List<Some_MethodResult> results = ctx.Get_Some_Method(parameter1, parameter2, parameter3).ToList();

        var colnames = ctx.Mapping.MappingSource.GetModel(typeof(SomeDataContext)).GetMetaType(typeof(Get_Some_MethodResult)).DataMembers;


        foreach (Get_Some_MethodResult r in results)
        {
            foreach (var colname in colnames)
            {
                string line = "\"" + r.GetType().GetField(colname.Name).ToString() + "\",";
                sb.Append(line);
            }
         }

Приведенное выше дает мне имя поля, и я ищу значение. GetMember(), похоже, не дает мне лучших результатов.

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

0
adrianstovall 3 Фев 2022 в 20:06

2 ответа

Сохраните результат GetField и вызовите для него GetValue, передав r в качестве параметра.

Но вы не хотите вызывать GetField внутри вложенного цикла. Прокрутите столбцы один раз, сохранив все результаты GetField() в массив FieldInfo[]. Затем внутри ваших вложенных циклов выберите из массива.

Если это недостаточно эффективно, вы можете использовать дерево выражений для построения Func<Get_Some_MethodResult, object> из каждого поля, которое обращается к этому полю любого произвольного объекта, и сохранить их массив вместо FieldInfo. (Для свойств это было возможно с использованием GetGetMethod и CreateDelegate перед деревьями выражений). Тогда вам вообще не понадобится какое-либо отражение внутри вложенных циклов.


Конечно, всей этой сложности можно было бы избежать, если бы вы пропустили сопоставление ORM и просто обработали IDataReader, возвращенное хранимой процедурой. Средство чтения данных обеспечивает простой индексированный доступ как к значениям столбцов, так и к значениям.

На самом деле довольно просто написать функцию, которая превращает любой IDataReader в CSV.

1
Ben Voigt 3 Фев 2022 в 20:17
Близко, но не сигара. Очевидно, GetField был не тем местом, где мне следовало искать. Я добавлю свой ответ в ближайшее время.
 – 
adrianstovall
3 Фев 2022 в 23:12
@adrianstovall: В своем вопросе вы сказали, что вернули имя от GetField(colname.Name).ToString(). Вы сейчас говорите, что код в вопросе НЕ получил имя?
 – 
Ben Voigt
4 Фев 2022 в 00:51

Итак, ответ состоит из нескольких частей. Спасибо моему коллеге Тони Количу за помощь в изучении этого.

Во-первых, именно GetProperties(), а не GetFields() я должен был искать значения столбца, возвращаемые sproc.

Знание этого очень помогло. Новый цикл выглядит так (пожалуйста, игнорируйте бит colval/boolean):

using (SomeDataContext ctx = new SomeDataContext())
        {
        List<Some_MethodResult> results = ctx.Get_Some_Method(parameter1, parameter2, parameter3).ToList();

        var colnames = ctx.Mapping.MappingSource.GetModel(typeof(SomeDataContext)).GetMetaType(typeof(Get_Some_MethodResult)).DataMembers;

        var props = typeof(Get_Some_MethodResult).GetProperties().Where(p => colnames.Any(n => p.Name == n.Name));

        foreach (Get_Some_MethodResult r in results)
        {
            foreach (var colname in colnames)
            {
                bool firstcol = true;
                foreach (var colname in colnames)
                {
                    var prop = props.FirstOrDefault(p => p.Name == colname.Name);
                    if (prop != null)
                    {
                        string colval = "";
                        if (!firstcol)
                        {
                            colval = ",\"" + prop.GetValue(r, null).ToString() + "\"";
                        }
                        else
                        {
                            colval = "\"" + prop.GetValue(r, null).ToString() + "\"";
                        }
                        //var field =
                        sb.Append(colval);
                        firstcol = false;
                    }
                }
                sb.AppendLine();
            }
         }

Теперь, что касается того, должен ли я был сделать это вообще, иногда бывает так много часов, которые можно потратить на проект, и это был путь наименьшего сопротивления. Спасибо всем, кто ответил!

0
adrianstovall 3 Фев 2022 в 23:29
Вам действительно следует использовать GetGetMethod(), о котором я упоминал в своем ответе, и делать это вне вложенных циклов (GetProperties() и GetGetMethod() требуют отражения, что очень дорого). Сделайте это только один раз, а затем повторно используйте метод получения для каждой последующей строки результатов.
 – 
Ben Voigt
4 Фев 2022 в 00:53