Как вывести несколько объектов по отношению к многозначному столбцу в Dynamic Linq - PullRequest
0 голосов
/ 29 января 2019

Сценарий: Я должен экспортировать файл Excel, который будет содержать список деталей.Мы позволили пользователю выбирать столбцы и получать только данные выбранных столбцов в экспортированном файле.Поскольку это динамический отчет, я не использую какой-либо конкретный класс для сопоставления отчета, так как это приведет к экспорту пустых заголовков столбцов в отчете, что не нужно.Я использую Dynamic Linq для решения этого сценария.

У меня есть список динамических объектов, извлеченных из динамического linq.

[
    {"CleanPartNo":"Test","Description":"test","AliasPartNo":["258","145","2313","12322"]},
    {"CleanPartNo":"Test1","Description":"test1","AliasPartNo":[]}
]

Как я могу получить 4 строки из этого json, как

enter image description here

Обратите внимание, что я не могу использовать строго типизированный объект для десериализации / сопоставления его с помощью JSON.Net

Обновление Ниже приведен код:

 public class Part
    {
        public int Id { get; set; }
        public string CleanPartNo { get; set; }
        public string Description { get; set; }
        public List<PartAlias> AliasPartNo { get; set; }
    }

public class PartAlias
    {
        public int PartId { get; set; }
        public int PartAliasId { get; set; }
        public string AliasPartNo { get; set; }
    }




var aliases = new List<PartAlias> {
                new PartAlias{AliasPartNo="258" },
                new PartAlias{AliasPartNo="145" },
                new PartAlias{AliasPartNo="2313" },
                new PartAlias{AliasPartNo="12322" }
            };
List<Part> results = new List<Part> {
                new Part{CleanPartNo="Test", Description= "test", PartAlias=aliases  },
                new Part{CleanPartNo="Test1", Description= "test1" }

            };

var filters = "CleanPartNo,Description, PartAlias.Select(AliasPartNo) as AliasPartNo";
var dynamicObject = JsonConvert.SerializeObject(results.AsQueryable().Select($"new ({filters})"));

в переменной dynamicObject. Я получаю json, упомянутый выше

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Из предоставленной вами json вы можете получить значения, сгруппированные по их имени следующим образом:

var array = JArray.Parse(json);
var lookup = array.SelectMany(x => x.Children<JProperty>()).ToLookup(x => x.Name, x => x.Value);

, тогда это всего лишь простой цикл поиска для заполнения столбцов Excel.

Однако я бы предложил сделать расклеивание перед JSON.Некоторое время я пытался сделать это, даже не зная имен столбцов, которые являются массивами, но я потерпел неудачу, и, поскольку это ваша работа, я больше не буду пытаться: P

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

0 голосов
/ 29 января 2019

Отказ от ответственности : следующее опирается на анонимные классы, которые не совсем совпадают с динамическим LINQ (не совсем), но я подумал, что это может помочь в любом случае, в зависимости от ваших потребностей, поэтому я решилчтобы опубликовать его.

Чтобы сгладить ваш список, вы можете использовать вложенный Select, за которым следует SelectMany ( Отказ от ответственности: Это предполагает, что каждая часть имеет хотя бы один псевдонимполный код см. ниже)

var flattenedResult = result.Select(part => part.AliasPartNumber.Select(alias => new 
                                                                                 { 
                                                                                     CleanPartNo = part.CleanPartNo, 
                                                                                     Description = part.Description,
                                                                                     AliasPartNo = alias.AliasPartNo
                                                                                 })
                            .SelectMany(part => part);

Сначала вы проецируете свои предметы из result (внешний Select).Проекция проецирует каждый элемент на IEnumerable анонимного типа, в котором каждый элемент соответствует номеру псевдонима.Поскольку внешний Select даст IEnumerable<IEnumerable> (или что-то похожее), мы используем SelectMany, чтобы получить один IEnumerable всех предметов из вашего вложенного IEnumerables.Теперь вы можете сериализовать IEnumerable экземпляров анонимного класса с помощью JsonConvert

var json = sonConvert.SerializeObject(flatResults);

Обработка деталей без псевдонимов

Если псевдонимов нет, внутренний выбор приведет к пустомуIEnumerable, следовательно, нам придется ввести специальный случай

var selector = (Part part) => part.AliasPartNumber?.Any() == true
                                  ? part.AliasPartNumber.Select(alias => new 
                                                                         { 
                                                                             CleanPartNo = part.CleanPartNo, 
                                                                             Description = part.Description,
                                                                             AliasPartNo = alias.AliasPartNo
                                                                         })
                                  : new[]
                                    {
                                        new 
                                        { 
                                            CleanPartNo = part.CleanPartNo, 
                                            Description = part.Description,
                                            AliasPartNo = alias.AliasPartNo
                                        }
                                    };
var flattenedResult = result.Select(selector).SelectMany(item => item);
...