Короткий способ получить динамические объекты из запроса выбора LINQ в XML?

Есть ли синтаксис инициализации ExpandoObject, который я могу использовать в своих интересах в запросе LINQ to XML для краткости?

Примечание. Результаты запроса предназначены для передачи за пределы текущей сборки, поэтому анонимные типы исключены (узнайте, почему здесь).

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

public IEnumerable<dynamic> ParseUserXml(string strXmlUser) {

var qClients =
    from client in xdoc.Root.Element(XKey.clients).Elements(XKey.client)
    // client object

    // I cannot get ExpandoObject to initialize inline 
    select new ExpandoObject() {     // try initialization syntax, COMPILE ERR
        OnlineDetails = new
        {
            Password = client.Element(XKey.onlineDetails).
                Element(XKey.password).Value,
            Roles = client.Element(XKey.onlineDetails).
                Element(XKey.roles).Elements(XKey.roleId).
                Select(xroleid => xroleid.Value)
            // More online detail fields TBD
        },

        // etc ....

        // YIELD DYNAMIC OBJECTS BACK THROUGH IEnumerable<dynamic>...
        foreach (var client in qClients)
        {
            yield return client;
        }

Более сложными решениями для работы этого кода могут быть:

  • вместо этого создайте конкретный класс и инициализируйте его (но я не хочу создавать их кучу).
  • используйте анонимный тип и скопируйте его члены в динамический объект (несколько избыточный) и верните динамические объекты

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


person John K    schedule 01.03.2011    source источник


Ответы (3)


К сожалению, я не думаю, что вы сможете это сделать. Что вы можете сделать, так это создать вспомогательный метод и вызвать его.

var qClients =
    from client in xdoc.Root.Element(XKey.clients).Elements(XKey.client)
    // client object
    select ClientXmlToExpandoObject(client);

Помощник может выглядеть примерно так

public dynamic ClientXmlToExpandoObject(System.Xml.Linq.XElement client)
{
    dynamic result = new ExpandoObject();
    result.OnlineDetails = new
        {
            Password = client.Element(XKey.onlineDetails).
                Element(XKey.password).Value,
            Roles = client.Element(XKey.onlineDetails).
                Element(XKey.roles).Elements(XKey.roleId).
                Select(xroleid => xroleid.Value)
            // More online detail fields TBD
        };
    return result;
}
person David Ruttka    schedule 01.03.2011

Вот классное решение, DynamicXml: http://blogs.captechconsulting.com/blog/kevin-hazzard/fluent-xml-parsing-using-cs-dynamic-type-part-1

person Kalman Speier    schedule 01.03.2011

Я закончил тем, что использовал один из ответов кода Джона Скита из связанного вопроса. Образец кода скопирован здесь для потомков. Он использует необработанные классы, а не синтаксис запроса.

// Code answer by Jon Skeet.
var qClients = xdoc.Root
       .Element(XKey.clients)
       .Elements(XKey.client)
       .Select(client => {
           dynamic o = new ExpandoObject();
           o.OnlineDetails = new ExpandoObject();
           o.OnlineDetails.Password = client.Element(XKey.onlineDetails)
                                            .Element(XKey.password).Value;
           o.OnlineDetails.Roles = client.Element(XKey.onlineDetails)
                                         .Element(XKey.roles)
                                         .Elements(XKey.roleId)
                                         .Select(xroleid => xroleid.Value);
           return o; 
       });
person John K    schedule 01.03.2011