将对象的集合转换为具体类的集合

时间:2014-12-05 08:41:37

标签: c# generic-collections

考虑一下,我有以下方法:

public T Resolve<T>()
{
    var targetType = typeof(T);

    if (targetType.IsGenericType
          && targetType.GetGenerictTypeDefinition() == typeof(IEnumerable<>))
    {
        List<object> collection = this.ResolveCollection(targetType);

        return (T)(object)collection;
    }

    return (T)this.ResolveSingle(targetType);
}

样本用法:

IEnumerable<IFoo> coll = myClass.Resolve<IEnumerable<IFoo>>();

很明显,由于协方差,示例会抛出无效投射的异常 - 尽管List<object>包含IEnumerable<IFoo>实现,但我们无法将collection强制转换为IFooResolve。 在使用反射和非泛型方法时,是否有针对该问题的解决方法?我不想更改Cast签名,因此我没有使用LINQ {{1}}的通用类型的项目。

2 个答案:

答案 0 :(得分:1)

这将是丑陋的。您可以在&#34;制作&#34;之后调用Linq方法Enumerable.Cast<>。它,即填写通用参数。

这是一个扩展方法:

public static TIEnumerable ToIEnumerable<TIEnumerable>(this IEnumerable<object> source)
{
  var type = typeof(TIEnumerable);
  if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(IEnumerable<>))
    throw new ArgumentException("Wrong type arg: " + type, "TIEnumerable");

  var methOpen = typeof(Enumerable).GetMethod("Cast");
  var methConstructed = methOpen.MakeGenericMethod(type.GenericTypeArguments[0]);

  return (TIEnumerable)methConstructed.Invoke(null, new object[] { source, });
}

(您甚至可以扩展非通用IEnumerable,因为Cast<>对此进行操作。)

然后if(在您的问题中)的正文可能是:

    List<object> collection = this.ResolveCollection(targetType);

    return collection.ToIEnumerable<T>();

如果你想要急切迭代并返回List<>,那就是:

    List<object> collection = this.ResolveCollection(targetType);

    return collection.ToIEnumerable<T>()
        .ToList();

答案 1 :(得分:0)

找到解决方法:

List<object> collection = this.ResolveCollection(targetType);

var itemType = targetType.GetGenericArguments()[0];
var listType =  typeof(List<>).MakeGenericType(itemType);

var listInstance = Activator.CreateInstance(listType, new object[0]) as IList;
foreach (var instance in collection) 
{
    listInstance.Add(instance);
}

return (T)listInstance;

然后,施法就像一个chram。