Рекурсивная фильтрация Linq для объектов
можно рекурсивно фильтровать все элементы в рекурсивном дереве с помощью linq для объектов.
Это модель, которую я использую. Это дается мне другим приложением
public class Menu
{
public string Name{get;set;}
public string Roles{get;set;}
public List<Menu> Children{get;set;}
}
Когда пользователь входит в мое приложение, мне нужно проверить роли пользователей против ролей, указанных в пункте меню. Я знаю, что могу написать рекурсивный метод, который проверяет это, используя цикл for.
В любом случае, я получаю это, используя "MenuList.Where(.. проверить роли)
заблаговременно
Ответы
Ответ 1
Я бы просто реализовал другой метод в классе Menu
:
public class Menu
{
public string Name { get; set; }
public string Roles { get; set; }
public List<Menu> Children { get; set; }
/// <summary>
/// Checks whether this object or any of its children are in the specified role
/// </summary>
public bool InRole(string role)
{
if (role == null)
{
throw new ArgumentNullException("role");
}
var inRole = (this.Roles ?? String.Empty).Contains(role);
if (!inRole & Children != null)
{
return Children.Any(child => child.InRole(role));
}
return inRole;
}
}
И тогда вы можете просто написать запросы LINQ, например:
var inRole = menuList.Where(menu => menu.InRole("admin"));
Он будет работать рекурсивно.
Ответ 2
Попробуйте этот метод расширения:
public static IEnumerable<T> Flatten<T, R>(this IEnumerable<T> source, Func<T, R> recursion) where R : IEnumerable<T>
{
return source.SelectMany(x => (recursion(x) != null && recursion(x).Any()) ? recursion(x).Flatten(recursion) : null)
.Where(x => x != null);
}
И вы можете использовать его следующим образом:
menu.Flatten(x => x.Children).Where(x => x.Roles.Contains(role));