Manchmal gibt es die Problematik, dass Klassen Properties vom Typ der Klasse selbst halten. Das heißt letztendlich natürlich auch, dass Instanzen dieser Klasse "in sich selbst verschachtelt" werden können.
Beispiel:
//Klasse zum Halten der Daten
public class Test
{
public Test()
{
}
public Test InnerTest { get; set; }
public string Text { get; set; }
public int Count { get; set; }
}
class Program
{
public static void Main()
{
//Verschachtelung erzeugen
Test foobar = new Test()
{
Text = "Level1",
InnerTest = new Test()
{
Text = "Level2",
Count = 33,
InnerTest = new Test()
{
InnerTest = new Test()
{
Text = "Level3",
Count = 44
}
}
}
};
//Instanzen des Properties "Text" mit dem Wert "Level3" suchen
IEnumerable<Test> level3Result = foobar.DeepWhere(p => p.Text == "Level3");
//Instanzen des Properties "Count" mit dem Wert "33" suchen
IEnumerable<Test> countResult = foobar.DeepWhere(p => p.Count == 33);
}
}
Dieses Snippet dient dazu, diese "Verschachtelung" aufzulösen und die verschiedenen Instanzen durchsuchen zu können.
Die eigentliche Funktionalität stellt die Extension-Function "DeepWhere" bereit. Diese Methode liefert ein IEnumerable der Instanzen zurück, die den angegebenen Suchkritieren entsprechen.
Das entsprechende Snippet erfordert die
.NET-Framework Version 4.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public static class Extension
{
/// <summary>
/// Filters a sequence of values recursive based on a predicate.
/// </summary>
/// <param name="predicate">A function to test each element for a condition.</param>
/// <returns>An IEnumerable that contains elements from the input sequence that satisfy the condition.</returns>
public static IEnumerable<TSource> DeepWhere<TSource>(this TSource instance, Func<TSource, bool> predicate)
{
if (instance != null)
{
if (predicate(instance))
yield return instance;
foreach (TSource source in instance
.GetType().GetProperties()
.Where(p => p.PropertyType.Equals(typeof(TSource)))
.SelectMany(p => ((TSource)p.GetValue(instance)).DeepWhere(predicate)))
yield return source;
}
}
}
2 Kommentare zum Snippet