当T为IEnumerable时,将类型T的泛型参数转换为List <tp> <tp> </tp> </tp>

时间:2014-03-19 08:29:55

标签: c# linq generics reflection linq-to-objects

我的应用程序有一个缓存值的方法。我需要第二个方法来检查类型T的泛型参数是否实现IEnumerable而不实现IList。如果答案是肯定的,那么该方法应该执行.ToList并将其强制转换为T(参见代码示例中的注释)。

你能告诉我怎么做.ToList()来返回一个被转换回T的List吗?(它有可能吗?)

这样的事情:

public T ToListIfIEnumerable<T>(T value)
{
    var needToCovert = TypeImplementsGenericIEnumerableButNotGenericIList(value);

    if (!needToCovert)
    {
        return value;
    }

    // return value.ToList() <-- How to do that???
}

private bool TypeImplementsGenericIEnumerableButNotGenericIList<T>(T value)
{
    var type = value.GetType();

    var interfaces = type.GetInterfaces();
    var gi = typeof(IEnumerable<>);
    var gl = typeof(IList<>);

    // It would be better if the next lines did't compare strings!
    // Suggestions welcome...
    var implementsIEnumerable = interfaces.Any(
        i => i.IsGenericType && i.Name == gi.Name && i.Namespace == gi.Namespace);
    var implementsIList = interfaces.Any(
        i => i.IsGenericType && i.Name == gl.Name && i.Namespace == gl.Namespace);

    return implementsIEnumerable && !implementsIList;
}

Backgrond信息: 使用该方法的对象执行类似Lazy的操作。缓存IEnumerable在以下示例中没有多大意义:Enumerable.Range(1, 3).Select(i => Guid.NewGuid())每次调用它时都会提供新的Guid。这就是为什么我想做一个ToList()。

1 个答案:

答案 0 :(得分:4)

如果您不介意使用dynamic

,动态类型和重载可能会有所帮助
object ConvertToListIfNecessary(dynamic input)
{
    return MaybeToList(input);
}

private IList<T> MaybeToList<T>(IEnumerable<T> input)
{
    return input.ToList();
}

private IList<T> MaybeToList<T>(IList<T> input)
{
    return input;
}

private object MaybeToList(object input)
{
    // Take whatever action you want if the input *doesn't* implement
    // IEnumerable<T>
}

基本上,这会让dynamic背后的聪明才智为你做蹩脚的反思工作。它可能不像手工推出的东西那么快,但它很可能很多更容易做对。