У меня есть такой список (уже открытый с отладчиком Visual Studio):

enter image description here

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

я могу попробовать это для проверки, но, учитывая только элементы верхнего уровня, те, у которых индекс 0, не распространяются на все:

AttachmentFolders childWithId17 = ApplicationContext.Instance.companyList[0].AttachmentFolders.SelectMany(parent => parent.AttachmentFolder)
                             .FirstOrDefault(child => child.FID == "835A09A2-9D60-46CC-A2BE-D4CBC4C81860");

другое изображение, чтобы лучше понять

enter image description here

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

структура класса:

public class AttachmentFolders
    {
        public int id { get; set; }
        public String FID { get; set; }
        public String Name { get; set; }
        public String CPID { get; set; }
        public String ParentFID { get; set; }

            public List<Attachment> Attachments { get; set; }
            public List<AttachmentFolders> AttachmentFolder { get; set; }
        }

public class Attachment
    {
        public int id { get; set; }
        public String ATID { get; set; }
        public String Name { get; set; }
        public String CreatorID { get; set; }
        public String FID { get; set; }
        public String Extension { get; set; }
        public String Description { get; set; }
        public int Status { get; set; }
        public String CPID { get; set; }
        public int FileSize { get; set; }
        public DateTime CreationDate { get; set; }
        public DateTime ModifiedDate { get; set; }
        public int AttachmentType { get; set; }
        public int ValidityType { get; set; }
        public List<Revisions> Revisions { get; set; }
        public String AWID { get; set; }
        public String WAID { get; set; }
        public String WatermarkPositions { get; set; }
        public Boolean Serveroffline { get; set; }
        public Boolean IsFavourite { get; set; }
        public DateTime LastOpenDate { get; set; }
        public int Priority { get; set; }
        public String CreatorFirstName { get; set; }
        public String CreatorLastName { get; set; }
        public String ModifiedByFirstName { get; set; }
        public String ModifiedByLastName { get; set; }
        public String[] Capabilities { get; set; }
    }

Спасибо вам всем.

1
Mr. Developer 26 Фев 2016 в 13:15

2 ответа

Лучший ответ

Вы можете написать что-то вроде расширения SelectDeep, как в этом ответе Марка: Выражение рекурсии в LINQ

А затем используйте его в своем коде вместо SelectMany:

AttachmentFolders child = companyList[0].AttachmentFolders
    .SelectDeep(parent => parent.AttachmentFolder)
    .FirstOrDefault(child => child.FID == "835A09A2-9D60-46CC-A2BE-D4CBC4C81860");

Метод SelectDeep выглядит следующим образом:

public static class EnumerableExtensions
{
    public static IEnumerable<T> SelectDeep<T>(
        this IEnumerable<T> source, Func<T, IEnumerable<T>> selector) {
        foreach (T item in source) {
            yield return item;
            foreach (T subItem in SelectDeep(selector(item), selector)) {
                yield return subItem;
            }
        }
    }
}
1
Community 23 Май 2017 в 10:30

Это типичный случай рекурсии. Вы можете попробовать выполнить поиск в плоской древовидной структуре, как это сделано в this или этот ответ.

Если вы столкнетесь с низкой производительностью этого решения, я бы подумал о создании вспомогательного объекта Dictionary<string, AttachmentFolders>, который бы содержал все (под) ссылки на папки для быстрого доступа, например

IEnumerable<AttachmentFolders> Flatten(AttachmentFolders f)
{
    var fs = new[] { f };
    return f.Children == null? fs : fs.Concat(f.Children.SelectMany(Flatten));
}

Dictionary<string, AttachmentFolders> GenerateCache(AttachmentFolders firstFolder)
{
    return Flatten(firstFolder).ToDictionary(f => f.FID, f => f);
}

Затем однократно при запуске:

Dictionary<string, AttachmentFolders> Cache = GenerateCache(firstFolder);

И каждый раз, когда делается запрос:

if(Cache.ContainsKey(fid)) return Cache[fid];
else throw new Exception("Handle not found FID here");
-1
Community 23 Май 2017 в 10:30