i am attempting to create an
IEnumrable<PropertyInfo>
iv'e got a method called Disassemble which iterates recursively throw a given object and all it's child objects of it's properties .
please do not concern your self with the Inner wrapper objects of type INameValueWrapper
The problem below is when i encounter a property which is a Class i wan't to call Disassemble on it as well and add it to the same iteration of the IEnumrable , the Dissasemble does not occur again when it is called where i put the comment : // The problem is here .
public static IEnumerable<T> Dissasemble<T>(this object sourceObj) where T : INameValueWrapper
{
var properties = sourceObj.GetType().GetProperties();
foreach (var prop in properties)
{
var wrapper = (T)prop.WrapPropertyInfo(sourceObj);
yield return wrapper;
if (wrapper is CollectionPropertyInfoWrapper)
{
var colWrapper = wrapper as CollectionPropertyInfoWrapper;
var collection = (IList)colWrapper.Value;
int index = 0;
foreach (var item in collection)
{
yield return (T)item.WrapItem(collection, index + 1);
index++;
}
}
else
{
var propWrapper = wrapper as PropertyInfoWrapper;
if (!propWrapper.IsPrimitive)
{
var childObject = prop.GetValue(sourceObj);
childObject.Dissasemble<T>(); // here is the problem
}
}
}
yield break;
}
1) Why does it not get called and added to the iteration ?
2) What is the work around this issue ? ,
i could call childObject.Dissasemble<T>().ToList()
and then iterate that collection calling yield return on it's items
but that seems like re doing something i already did.
thanks in advance.
You're calling the method, but then ignoring the results. You may want something like:
foreach (var item in childObject.Disassemble<T>())
{
yield return item;
}
I think you're a bit confused about what yield return
does - it only yields a value in the sequence returned by the currently-executing method. It doesn't add a value to some global sequence. If you ignore the value returned by the recursive Disassemble
call, the code won't even execute as iterator blocks are lazy. (They only execute code when they're asked for another value.)
Also, you don't need the yield break;
at the end of your method.
Note that this if the recursion goes deep, this use of iterator blocks can be inefficient. That may well not be a problem for you, but it's something to think about. See posts by Wes Dyer and Eric Lippert about this.
See more on this question at Stackoverflow