How can I list an object of type `T` when it is IEnumerable

This is a little hard to explain. So there it is.

I have a function like this:

public T FooBar<T>(Func<T> function)
{
   T returnData = function();

   // want to iterate through returnData to do something to it

   return returnData;
}

If returnData(T) is a list IEnumerable, I would like to list through returnDatato modify its contents using reflection. But I can’t do it. When I try to use returnDatafor an enumerated type, I get an exception:

Unable to create object of type

'System.Collections.Generic.List`1 [Cars]

enter

'System.Collections.Generic.List`1 [System.Object]'.

I will not know that the return type will be a list of "cars", for example, ahead of time, only at runtime. Therefore, I have to check the use of reflection, if it is a list, and then try to pass it so that I can list it.

. returnData, T?

+5
4

T, :

public T FooBar<T>(Func<T> function) where T : IEnumerable
{
    // T is not strongly typed for the enumerated item

(w.r.t. T):

public IEnumerable<T> FooBar<T>(Func<IEnumerable<T>> function)

, .


, , , T returnData. , FooBar() a List<Car>, T List<Car>, List<>. List<U>, U - - .

U, , , T. , , non IEnumerable<U> , Func<IEnumerable<T>>.

, FooBar<T> .

+6
if (returnData is System.Collections.IEnumerable)
{
   foreach (object o in (System.Collections.IEnumerable)returnData)
   {
      // Do something.
   }
}

, :

public T FooBar<T>(Func<IEnumerable<T>> function) 
+4

IEnumerable IEnumerable<T>? IEnumerable foreach. , , object i.e.:

foreach(object item in (IEnumerable)T){...}

, T IEnumerable.

+2

IEnumerable IEnumerable Of T ... . , IEnumerable Of T IEnumerable, - .

The following worked for me in a small test that I wrote - I hope you will be enough for you to do what you need.

Here are the meat and potatoes:

class FooBarOfT
{
    public T FooBar<T>(Func<T> function)
    {
        T returnData = function();

        //Want to iterate through returnData to do something to it.
        if (returnData is IEnumerable) 
        {
            // get generic type argument
            var returnDataType = returnData.GetType();

            if (returnDataType.IsGenericType)
            {
                // this is a System.Collections.Generic.IEnumerable<T> -- get the generic type argument to loop through it
                Type genericArgument = returnDataType.GetGenericArguments()[0];

                var genericEnumerator =
                    typeof(System.Collections.Generic.IEnumerable<>)
                        .MakeGenericType(genericArgument)
                        .GetMethod("GetEnumerator")
                        .Invoke(returnData, null);

                IEnumerator enm = genericEnumerator as IEnumerator;
                while (enm.MoveNext())
                {
                    var item = enm.Current;
                    Console.WriteLine(string.Format("Type : {0}", item.GetType().Name));
                }

            }
            else
            {
                // this is an System.Collections.IEnumerable (not generic)
                foreach (var obj in (returnData as IEnumerable))
                {
                    // do something with your object
                }
            }
        }

        return returnData;
    }
}

I also created some supporting test classes:

class Foo
{
    private string _fooText;

    public Foo(string fooText)
    {
        _fooText = fooText;
    }
    public string Execute()
    {
        return string.Format("executed! with {0} !", _fooText);
    }
}

class Bar
{
    public string BarContent { get; set; }
}

And a small console application to run some tests:

class Program
{
    static void Main(string[] args)
    {
        // tests
        Func<string> stringFunc = () => 
            "hello!";

        Func<List<Foo>> listFooFunc = () => 
            new List<Foo> 
            { 
                new Foo("Hello!"),
                new Foo("World!")
            };

        Func<IEnumerable> ienumerableFooFunc = () =>
            new Hashtable
            {
                { "ItemOne", "Foo" },
                { "ItemTwo", "Bar" }
            };


        var fooBarOfT = new FooBarOfT();

        fooBarOfT.FooBar(stringFunc);
        fooBarOfT.FooBar(listFooFunc);
        fooBarOfT.FooBar(ienumerableFooFunc);

        Console.ReadKey();
    }
}
+1
source

All Articles