为泛型方法传递具体类型参数时返回通用IEnumerable

时间:2013-07-18 14:34:11

标签: c# .net generics dynamic types

此代码示例取自此回答https://stackoverflow.com/a/16491759/98706

public static Boolean PurgeDataObject(this IDataObject dataObject, Guid uid)
{
    return PurgeDataObjectImpl((dynamic) dataObject, uid);
}

private static Boolean PurgeDataObjectImpl<T>(T dataObject, Guid uid)
    where T : IDataObject
{
    return DataProvider.DeleteDataObject<T>(uid, DataProvider.GetConnection());
}

我有类似的情况,我希望在执行时根据类型返回相关的EF实体,尝试清理一些现有的继承代码,如下所示:(

不同之处在于我希望函数返回IEnumerable<T>

GetFilteredData没有T的概念,所以我得到The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)的编译错误

    private IEnumerable<T> GetFilteredData(Type entityType, SortedList<string, string> filterList, List<int> weeks)
    {
        return GetFilteredDataImpl((dynamic)entityType, filterList, weeks);
    }

    private IEnumerable<T> GetFilteredDataImpl<T>(T entityType, SortedList<string, string> filterList, List<int> weeks) where T : EntityObject
    {
        var data = _modelContext.CreateObjectSet<T>().AsExpandable();
          // do more filtering and then call .ToList() to return a List<T>
    }

1 个答案:

答案 0 :(得分:1)

如果不使用反射,则无法将Type类转换为通用T参数。该参数也需要作为方法的一部分出现。

Jon Skeet通过示例结合泛型使用类型推断,以保证类型安全并简化通用代码。不幸的是,您将使用Type和反射来失去该类型的安全性。

private IEnumerable<EntityObject> GetFilteredData(Type entityType,
                                                  SortedList<string, string> filterList,
                                                  List<int> weeks)
{
    var method = typeof(<class>).GetMethod("GetFilteredDataImpl");
    var generic = method.MakeGenericMethod(entityType);
    return (IEnumerable<EntityObject>)generic.Invoke(this, new[] { filterList, weeks });
}

private IEnumerable<T> GetFilteredDataImpl<T>(SortedList<string, string> filterList,
                                              List<int> weeks)
    where T : EntityObject
{
    var data = _modelContext.CreateObjectSet<T>().AsExpandable();
      // do more filtering and then call .ToList() to return a List<T>
}

但是,您可以创建一个要传入的对象。

private IEnumerable<EntityObject> GetFilteredData(Type entityType, SortedList<string, string> filterList, List<int> weeks)
{
    var instance = (EntityObject)Activator.CreateInstance(entityType);
    return GetFilteredDataImpl((dynamic)instance, filterList, weeks);
}

private IEnumerable<T> GetFilteredDataImpl<T>(T entityType, SortedList<string, string> filterList, List<int> weeks) where T : EntityObject
{
    var data = _modelContext.CreateObjectSet<T>().AsExpandable();
      // do more filtering and then call .ToList() to return a List<T>
}

这仍然会返回IEnumerable<EntityObject>,但它会产生垃圾,而您正在为ArgumentException交换InvalidCastException