简体   繁体   English

将IEnumerable转换为IEnumerable <T> 当T在编译时未知时

[英]Cast IEnumerable to IEnumerable<T> when T is unknown at compile time

I have a sorting extension method with the following signature: 我有一个带有以下签名的排序扩展方法:

public static IEnumerable<T> CustomSort<T>(this IEnumerable<T> source, string sortProperties)

We wrote it a while back and it has been doing its thing. 我们写了一段时间,它一直在做它的事情。 Now I am creating a custom control and the DataSource property is an IEnumerable (non-generic). 现在我正在创建一个自定义控件,DataSource属性是一个IEnumerable(非泛型)。 Is there any way to get the type of the objects in a non-generic IEnumerable? 有没有办法在非通用的IEnumerable中获取对象的类型?

I am sure the problem of "sort a custom control data source" has been solved a million times, but I just can't seem to find a solution. 我确信“排序自定义控制数据源”的问题已经解决了一百万次,但我似乎无法找到解决方案。

There is a fundamental issue here that a type can implement IEnumerable-of-T for multiple T at the same time. 这里存在一个基本问题,即类型可以同时为多个T实现IEnumerable-of-T。 But if we exclude that case, a cheeky approach is: 但如果我们排除这种情况,那么一种厚颜无耻的方法是:

void Evil<T>(IEnumerable<T> data) {...}

IEnumerable source = ...
dynamic cheeky = source;
Evil(cheeky);

This basically offloads this problem to the DLR, letting your Evil-of-T method take it easy. 这基本上将此问题卸载到DLR,让您的Evil-of-T方法轻松实现。

Personally, I would just use 就个人而言,我会用

DataSource.Cast<object>()

and then you have an IEnumerable<object> that you can use in your CustomSort<T> function. 然后你有一个可以在CustomSort<T>函数中使用的IEnumerable<object> I am assuming here that this function can handle arbitrary objects already; 我在这里假设这个函数已经可以处理任意对象了; judging by the second parameter name I'm guessing that you're using Reflection in it anyway, so it should be fine. 根据第二个参数名称判断我猜你还在使用Reflection,所以应该没问题。 Just make sure it uses each object's GetType() when reflecting on it, not typeof(T) , because typeof(T) will obviously be object and it won't get the list of fields of the actual object. 只要确保它在反射时使用每个对象的GetType() ,而不是typeof(T) ,因为typeof(T)显然是object ,它不会获得实际对象的字段列表。

Of course, if you actually know the type of all the objects in the data source at compile-time, you might want to use that type instead, eg: 当然,如果您在编译时实际知道数据源中所有对象的类型,则可能需要使用该类型,例如:

DataSource.Cast<Customer>()

You could create an extension method that will return the correct type at runtime: 您可以创建一个在运行时返回正确类型的扩展方法:

public static class LinqExtensions
{
    public static Type GetElementType(this IEnumerable source)
    {
        var enumerableType = source.GetType();
        if (enumerableType.IsArray)
        {
            return enumerableType.GetElementType();
        }
        if (enumerableType.IsGenericType)
        {
            return enumerableType.GetGenericArguments().First();
        }
        return null;
    }
}

Update: I've added the mechanism that I would use to perform the generic-specific IEnumerable<T> sorting on the non-generic IEnumerable 更新:我添加了用于在非通用IEnumerable上执行特定于通用的IEnumerable<T>排序的机制

public static class SortingExtensions
{
    public static IEnumerable<T> CustomSort<T>(this IEnumerable<T> source, string sortProperties)
    {
        // sort here
    }

    public static IEnumerable CustomSort(this IEnumerable source, string sortProperties)
    {
        var elementType = source.GetElementType();
        var genericElementType = typeof (IEnumerable<>).MakeGenericType(elementType);

        var sortMethod = typeof (SortingExtensions).GetMethod(
            "CustomSort", 
            BindingFlags.Public | BindingFlags.Static,
            null, 
            new [] {genericElementType, typeof (string)},
            null);

        return (IEnumerable) sortMethod.Invoke(null, new object[] {source, sortProperties});
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM