Как получить доступ к уже определенному свойству анонимного объекта linq?

1

У меня есть словарный словарь, анс и запрос LINQ:

ans = new Dictionary<string,string>();
ans = LoadAnswers();

var milestones = LoadMilestones(session).Select(
                    m => new
                    {
                        milestoneid = GetSafeValue(m.Attribute("id").Value),
                        duedate = GetSafeValue(m.XPathValue("duedate")),
                        answer = ans[milestoneid]
                    }).ToArray()

Внутри объекта моей вехи у меня есть ответ свойства, где я хочу заполнить данные из объекта ans, используя milestoneid, который является уже определенным свойством. Но этот код не будет компилироваться, при этом ошибка squiggly говорит, что тип x не содержит определения для milestoneid.

Поскольку GetSafeValue() является огромным методом, я не хочу использовать его снова, чтобы заполнить свойство answer.

Q1) Как я могу использовать свойство milestoneid для моего ответа?

Q2) Кроме того, я хочу использовать ans.TrygetValue(), чтобы избежать нулевых исключений в этом запросе. Как это сделать?

Благодарю.

  • 0
    Похоже, вы десериализуете данные XML. Почему вы не используете библиотеку для десериализации?
  • 0
    @Aron Арон, возможно, в будущем, но это всего лишь пример сценария. В будущем мы можем столкнуться с подобной ситуацией, даже если не имеем дело с XML.
Показать ещё 5 комментариев
Теги:
linq
anonymous-types

3 ответа

3
Лучший ответ

Выражение после => может быть полнофункциональным анонимным методом, который возвращает новый тип. Следовательно, вы можете поднять значения так:

m => {
    var id = GetSafeValue(m.Attribute("id").Value);
    string answer;
    return new {
        milestoneid = id,
        duedate = GetSafeValue(m.XPathValue("duedate")),
        answer = ans.TryGetValue(id, out answer) ? answer : null
    }
}
  • 0
    краткий и точный :) ... а также первый !!!
3

Вам не разрешено использовать переменную, которая назначается объекту anon, который вы возвращаете. Значение, milestoneid является свойством нового объекта, а не локальной переменной. Вы можете сделать это: ans[GetSafeValue(m.Attribute("id").Value)]. Это добавляет некоторые неудачные дублирования, хотя я бы рекомендовал нечто большее:

var milestones = LoadMilestones(session).Select(
                m => {
                    var id = GetSafeValue(m.Attribute("id").Value);
                    return new
                    {
                        milestoneid = id,
                        duedate = GetSafeValue(m.XPathValue("duedate")),
                        answer = loadStudentResponse ? null : ans[id]]
                    };
                }).ToArray()

Что касается второго вопроса, TryGetValue возвращает bool и имеет параметр out.

object answer; // the type should be whatever you are expecting.
ans.TryGetValue(id, out answer);

Может быть, что-то вроде:

var milestones = LoadMilestones(session).Select(
                m => {
                    var id = GetSafeValue(m.Attribute("id").Value);

                    object answer; // the type should be whatever you are expecting.
                    ans.TryGetValue(id, out answer);

                    return new
                    {
                        milestoneid = id,
                        duedate = GetSafeValue(m.XPathValue("duedate")),
                        answer = answer
                    };
                }).ToArray()
2

Вы можете повторить GetSafeValue(m.Attribute("id").Value) в индексере при получении ответа (который не является DRY) или вместо этого сделать второй прогон, чтобы добавить поля, полученные из начальной проекции:

var milestones = LoadMilestones(session)
                .Select(m => new
                {
                    milestoneid = GetSafeValue(m.Attribute("id").Value),
                    duedate = GetSafeValue(m.XPathValue("duedate")),
                })
                .Select(x => new 
                {
                   x.milestoneid,
                   x.duedate,
                   answer = ans[x.milestoneid]
                })
                .ToArray();

(neouser99 однопроходный расширенный лямбда-ответ лучше, ИМО)

Кроме того, я не уверен, что это фактический код, но обратите внимание, что приведенная ниже инициализация избыточна

var ans = new Dictionary<string,string>();
ans = LoadAnswers();

Допускается сводить к простому:

var ans = LoadAnswers();
  • 0
    это просто, чтобы сделать вопрос более ясным. :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню