Convert / Cast IEnumerable to IEnumerable

后端 未结 4 1150
甜味超标
甜味超标 2020-12-03 00:41

I have a class (A web control) that has a property of type IEnumerable and would like to work with the parameter using LINQ.

Is there any way to cast / convert / inv

相关标签:
4条回答
  • 2020-12-03 01:00

    This is years later, but I solved the List<Object> problem.

    void Method(IEnumerable source)
    {
        var enumerator = source.GetEnumerator();
        if (enumerator.MoveNext())
        {
            MethodInfo method = typeof(MyClass).GetMethod("Method2");
            MethodInfo generic;
            Type type = enumerator.Current.GetType();
            bool sameType = true;
    
            while (enumerator.MoveNext())
            {
                if (enumerator.Current.GetType() != type)
                {
                    sameType = false;
                    break;
                }
            }
    
            if (sameType)
                generic = method.MakeGenericMethod(type);
            else
                generic = method.MakeGenericMethod(typeof(object));
    
            generic.Invoke(this, new object[] { source });
        }
    }
    
    0 讨论(0)
  • 2020-12-03 01:02

    Does your Method2 really care what type it gets? If not, you could just call Cast<object>():

    void Method (IEnumerable source)
    {
        Method2(source.Cast<object>());
    }
    

    If you definitely need to get the right type, you'll need to use reflection.

    Something like:

    MethodInfo method = typeof(MyType).GetMethod("Method2");
    MethodInfo generic = method.MakeGenericMethod(type);
    generic.Invoke(this, new object[] {source});
    

    It's not ideal though... in particular, if source isn't exactly an IEnumerable<type> then the invocation will fail. For instance, if the first element happens to be a string, but source is a List<object>, you'll have problems.

    0 讨论(0)
  • 2020-12-03 01:05

    You probably want to refactor your code to use IEnumerable.Cast<T>

    Use it like this:

    IEnumerable mySet = GetData();
    var query = from x in mySet.Cast<int>()
                where x > 2
                select x;
    
    0 讨论(0)
  • 2020-12-03 01:08

    With .NET 4 you can just cast source to dynamic before passing it to method. This will cause the correct generic overload to be resolved at runtime without any ugly reflection code:

    void Method(IEnumerable source)
    {
        var enumerator = source.GetEnumerator();
    
        if (enumerator.MoveNext())
        {
            Method2((dynamic)source);
        }
    }
    

    As with Jon's second solution, this will only work if your source is actually an IEnumerable<T>. If it is a plain IEnumerable then you'll need to create another method that converts it to the correct IEnumerable<T> type, as in the following solution:

    IEnumerable<T> Convert<T>(IEnumerable source, T firstItem)
    {
        // Note: firstItem parameter is unused and is just for resolving type of T
        foreach(var item in source)
        {
            yield return (T)item;
        }
    }
    
    void Method(IEnumerable source)
    {
        var enumerator = source.GetEnumerator();
    
        if (enumerator.MoveNext())
        {
            dynamic firstItem = enumerator.Current;
            dynamic typedEnumerable = Convert(source, firstItem);
            Method2(typedEnumerable);
        }
    }
    
    0 讨论(0)
提交回复
热议问题