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

C# 为泛型方法传递具体类型参数时返回泛型IEnumerable,c#,.net,generics,dynamic,types,C#,.net,Generics,Dynamic,Types,此代码示例取自此答案 如果不使用反射,则无法将Type类转换为泛型T参数。参数也需要作为方法的一部分出现 Jon Skeet通过实例结合泛型使用类型推断,以保证类型安全并简化泛型代码。不幸的是,使用type和反射将失去该类型的安全性 private IEnumerable<EntityObject> GetFilteredData(Type entityType, SortedList

此代码示例取自此答案


如果不使用反射,则无法将
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 GetFilteredData(类型entityType,
分类列表过滤器列表,
名单(星期)
{
var method=typeof().GetMethod(“GetFilteredDataImpl”);
var generic=method.MakeGenericMethod(entityType);
return(IEnumerable)generic.Invoke(this,new[]{filterList,weeks});
}
私有IEnumerable GetFilteredataImpl(SortedList filterList,
名单(星期)
其中T:EntityObject
{
var data=_modelContext.CreateObjectSet().AsExpandable();
//执行更多筛选,然后调用.ToList()返回列表
}
但是,可以创建要传入的对象

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>
}
private IEnumerable GetFilteredData(类型entityType、SortedList filterList、列表周)
{
var instance=(EntityObject)Activator.CreateInstance(entityType);
返回GetFilteredDataImpl((动态)实例,filterList,weeks);
}
私有IEnumerable GetFilteredDataImpl(T entityType,SortedList filterList,List weeks),其中T:EntityObject
{
var data=_modelContext.CreateObjectSet().AsExpandable();
//执行更多筛选,然后调用.ToList()返回列表
}

这仍然会返回一个
IEnumerable
,但它会生成垃圾,并且您正在用
ArgumentException
换取
InvalidCastException

那么,在
GetFilteredData
中,编译器应该如何知道T是什么呢?它不受约束,也不被定义为参数。@LightStriker是的,我在问题中加了一条注释,说GetFilteredata没有t的概念,所以我得到了编译错误
我想我现在正在寻找另一种方法。你认为使用GetFilteredata的代码会是什么样子?如果我更改
getFilteredata
IEnumerable
由于
getFilteredataImpl
和使用
dynamic
,我现有的代码工作正常。。我不需要做进一步的改变。但我的问题是,我必须在其他函数中对返回的结果进行大量强制转换,以便设置正确的属性,这正是我试图避免的:(您遇到的问题是使用非泛型方法来获得泛型结果。从泛型到非泛型,您将丢失类型信息。感谢您的建议,我确实需要重新考虑这一点,以便与当前代码相适应。再次感谢。
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>
}