sppc42
sppc42

Reputation: 3292

Reflection: casting reflected type to generic with type as string and iterating over it

I have scoured around StackOverflow and found multiple related questions, but none that answers it 'completely'. I might be wrong in my understanding, but wanted to check it -

I have a class

public class Foo
{
     public List<Bar> Bars = new List<Bar>();
}

public class Bar
{
}

Due to some reflection craziness happening, this List is getting passed only as an object -

Foo f = new Foo();
object o = f;
CheckItem(o, "Bars");

// CheckItem has no clue about Bar class and is thus passed the 'Bars' Field name 
public void CheckItem(Object obj, string fieldName)
{
    var value = obj.GetType().GetField(fieldName).GetValue(obj); // returns f.Bars into value as object

    foreach (var bar in value.Bars) // won't compile as value is type object
}

so, I use MakeGenericType and Activator.CreateInstance magic

var genericClass = typeof(List<>).MakeGenericType(new[] {value.GetType().FieldType.GetGenericArguments()[0]}); // makes a generic of type List<Bar>
var o = Activator.CreateInstance(genericClass); // o is again of type object
foreach (var bar in o.Bars) // will fail again

SO - How do I call the foreach loop to iterate over the members. Every example I have seen around MakeGenericType ends at just creating the object o, none talks about how to access its members, esp in a foreach loop like above.

Appreciate any inputs.

Thanks

Upvotes: 2

Views: 791

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500665

If you don't need to know about the element type, all you need to do is cast to IEnumerable:

var sequence = (IEnumerable) value;
foreach (var item in sequence)
{
    // The type of the item variable is just object,
    // but each value will be a reference to a Bar
}

(I'd strongly recommend using private fields and exposing properties instead, by the way - but that's a different matter.)

Upvotes: 4

Related Questions