I have a List containing different kinds of objects and sometimes those objects have a list of their own.
This relationship needs to be encoded and it is the one that will drive your type constraint method.
Assuming you have control over your concrete object implementation, the encoding might look like this:
public interface INestedList
{
List<object> InnerList { get; }
}
public class ContainsNestedList : INestedList
{
public List<object> InnerList { get; }
public string Name { get; }
public ContainsNestedList(string name, List<object> innerList)
{
Name = name;
InnerList = innerList;
}
public override string ToString()
{
return Name;
}
}
Note: The Name
property of ContainsNestedList
is only there for visual identification purposes.
If you don't have control over the concrete object types, there should still be some sort of existing logic that gives you this T1
- T2
relationship, otherwise the premise of your problem doesn't hold up.
When you do foreach (var v in l)
in your code, because l
is a List<T1>
, v
is also a T1
. Furthermore, checking to see that v
's type is the type of loopLoopClass
means that T1
is either an object
(non-constrained type) or a descendant of the loopLoopClass
, the latter being translated to a constraint of where T1 : loopLoopClass
.
Given that you do loopBody.OfTypeRecursive<T2>()
afterwards, and that loopBody
is said to be List<object>
according to the comments, T1
is now established to be object
.
That would lead us down the following code path:
public static class ListExtensions
{
public static List<object> OfTypeRecursive<T>(this List<object> source)
where T : INestedList
{
var itemsToDigInto = source.OfType<T>().ToList();
var output = source.Except(itemsToDigInto.Cast<object>()).ToList();
foreach (T item in itemsToDigInto)
{
Console.WriteLine($"Extracting from InnerList of {item}");
output.AddRange(item.InnerList.OfTypeRecursive<T>());
Console.WriteLine($"Finished processing for {item}");
}
return output;
}
}
public class Program
{
public static void Main()
{
var x = 2;
var y = 4.3m;
var z = "sf";
var p = new ContainsNestedList("p", new List<object> { x, y });
var q = new ContainsNestedList("q", new List<object> { z, p });
var r = new ContainsNestedList("r", new List<object> { x, y, p, q });
var source = new List<object> { x, y, z, q, p, r };
var result = source.OfTypeRecursive<ContainsNestedList>();
result.ForEach(i => Console.WriteLine("{0}", i));
Console.ReadKey();
}
}
EDIT: Update to account for the following premise
you have a list of arbitrary objects. Some of these objects are of type ClassA
. Some of the other objects are of some other specific class, say ClassB
, which is defined as having an inner list of objects, some of which might also be ClassA
or ClassB
in type.
public static class ListExtensions
{
public static List<T> OfTypeRecursive<T, TU>(this List<object> source)
where TU : INestedList
{
var output = source.OfType<T>().ToList();
var itemsToDigInto = source.OfType<TU>();
foreach (TU item in itemsToDigInto)
{
Console.WriteLine($"Extracting from InnerList of {item}");
output.AddRange(item.InnerList.OfTypeRecursive<T, TU>());
Console.WriteLine($"Finished processing for {item}");
}
return output;
}
}