Нужна помощь в уменьшении цикломатической сложности запроса LINQ, используемого для построения строки JSON

#c# #json #linq #json.net #cyclomatic-complexity

#c# #json #linq #json.net #цикломатическая сложность

Вопрос:

У меня есть 5 различных источников данных (request, lsitCC, listSEDI, listSEDIFees и XmlRoot, загруженные в соответствующие объекты списка массива C #). Мне нужно создать запрос JSON путем объединения данных из всех этих источников на основе определенных условий. Я написал приведенный ниже код на C #, используя NewtonSoft.JSON. Цикломатическая сложность для этого запроса LINQ приближается к 40, что выше. Может кто-нибудь посоветовать, как можно уменьшить сложность. Заранее спасибо. Я предполагаю, что запрос довольно удобочитаем, пожалуйста, дайте мне знать, требуются ли встроенные комментарии.

     var input = from RequestNode in request
              select new
              {
                  Documents = (from objCC in lsitCC
                               where objCC.ID == RequestNode.ID
                               select new
                               {
                                   Request = (from objSEDI in listSEDI
                                                         where objSEDI.ID == objCC.ID amp;amp; RequestNode.POSTAL.Count(p => p.PID == objSEDI.PID) > 0
                                                         join Config in RequestNode.POSTAL on objSEDI.PID equals Config.PID
                                                         select new
                                                         {
                                                             ReqItem = (Config.ReqItem == null) ? "" : Config.ReqItem,
                                                             Code = (RequestNode.Code == null) ? "" : RequestNode.Code,
                                                             Camp = (RequestNode.Camp == null) ? "" : RequestNode.Camp,
                                                             CCT = new
                                                             {
                                                                 ID = (objCC.ID == null) ? "" : objCC.ID,
                                                                 Band = (RequestNode.Band == null) ? "" : RequestNode.Band,
                                                                 Context = (RequestNode.Context == null) ? 0 : RequestNode.Context,
                                                                 IsActive = (RequestNode.IsActive == null) ? false : RequestNode.IsActive,
                                                                 MaxLimit = (objCC.MaxLimit == null) ? 0 : objCC.MaxLimit,
                                                                 MinLimit = (objCC.MinLimit == null) ? 0 : objCC.MinLimit
                                                             },
                                                             User = RequestNode.User,
                                                             POSTAL = new
                                                             {
                                                                 PID = (objSEDI.PID == null) ? "" : objSEDI.PID,
                                                                 Type = (Config.Type == null) ? "" : Config.Type,
                                                                 Amount = (Config.Amount == null) ? 0 : Config.Amount,
                                                                 IsValid = (Config.IsValid == null) ? false : Config.IsValid,
                                                                 Code = (Config.Code == null) ? "" : Config.Code,                                                                        
                                                                 Infos = new
                                                                 {
                                                                     Info = (from objRoot in XMLRoot
                                                                             where objRoot.ID == objCC.ID amp;amp; objRoot.Channel == "Channel1" amp;amp; objRoot.Group == "GROUP_1" amp;amp; objRoot.Code == Config.Type.Substring(0, 3) amp;amp; objRoot.PIDCode == Config.Type.Substring(3, 1)
                                                                             select new
                                                                             {
                                                                                 InfoFrom = (objRoot.InfoFrom == null) ? "" : objRoot.InfoFrom,
                                                                                 Selection = (objRoot.Handling == null) ? "" : objRoot.Selection,
                                                                                 Rate = (objRoot.Rate == null) ? "" : objRoot.Rate                                                                                         
                                                                             })
                                                                 },
                                                                 POSTALFee = from objSEDIFee in listSEDIFees
                                                                              where objSEDIFee.ID == objCC.ID amp;amp; objSEDIFee.PID == objSEDI.PID
                                                                              select new
                                                                              {
                                                                                  BaseValue = (objSEDIFee.BaseValue == null) ? 0 : objSEDIFee.BaseValue,
                                                                                  UpdatedValue = (objSEDIFee.UpdatedValue == null) ? 0 : objSEDIFee.UpdatedValue,
                                                                                  BaseType = (objSEDIFee.BaseType == null) ? "" : objSEDIFee.BaseType,
                                                                                  UpdatedType = (objSEDIFee.UpdatedType == null) ? 0 : objSEDIFee.UpdatedType
                                                                              },
                                                                 OutputRoot = new
                                                                 {
                                                                     Output = from output in outputroot
                                                                             select new
                                                                             {
                                                                                 Type = 0,
                                                                                 SubType = 0,
                                                                                 OutputReference = 0                                                                                        
                                                                             }
                                                                 }
                                                             },

                                                         })
                               })
              };
    var streamRead = JsonConvert.SerializeObject(input, Newtonsoft.Json.Formatting.Indented);
  

Ответ №1:

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

Это будет означать, что вам придется либо отказаться от типов anon, либо использовать ключевое слово dynamic (это вообще сработает ?!)

Вам также может потребоваться взглянуть на какой-то шаблон сборки или промежуточное состояние.

При дальнейшей проверке выясняется, что вы вводите некоторую глобальную переменную на полпути запроса, например XMLRoot amp; listSEDIFees . Было бы лучше, если бы это было более явно. Вы также можете сократить чрезмерную работу, предварительно отфильтровав XMLRoot статическую часть вашего предложения where ( objRoot.Channel == "Channel1" amp;amp; objRoot.Group == "GROUP_1" ) вместо повторного запуска каждый раз. Может быть, что-то вроде

 var channel1Group1Info = XMLRoot.Where(objRoot=>objRoot.Channel == "Channel1" amp;amp; objRoot.Group == "GROUP_1").ToArray();
  

Остальное я бы просто отбирал по одной части за раз, уменьшая объем работы, выполняемой этим запросом.