我有一个问题。我有一个方法(过滤器),我想通过T动态。但是它不会接受。我可以这样做吗?
public List<T> Filter<T>(string TypeOfCompare)
{
List<T> ReturnList2 = new List<T>();
return ReturnList2;
}
IList MakeListOfType(Type listType)
{
Type listType1 = typeof(List<>);
Type specificListType = listType.MakeGenericType(listType1);
return (IList)Activator.CreateInstance(specificListType);
}
Filter < ConstructGenericList(h) > ("s");
答案 0 :(得分:1)
IList MakeListOfType(Type listType)
{
Type listType1 = typeof(List<>);
Type specificListType = listType.MakeGenericType(listType1);
return (IList)Activator.CreateInstance(specificListType);
}
反之亦然,你应该在泛型类型定义上调用MakeGenericType
,而不是在泛型类型参数上调用IList MakeListOfType(Type elementType)
{
Type listType = typeof(List<>);
Type specificListType = listType.MakeGenericType(elementType);
return (IList)Activator.CreateInstance(specificListType);
}
。所以代码变成了这个:
{{1}}
(请注意,我更改了变量名称以使代码更清晰)
答案 1 :(得分:0)
通用参数必须具有能够在编译时确定的类型(不需要使用某些其他语言所具有的功能类型推断)。因此,您不能只在尖括号之间添加一个函数来获得所需的类型。
修改强>
既然我知道你要做什么,我会完全建议一种不同的方法。
您提到您正在使用Entity Framework,并且您尝试使用一种方法来获取不同类型对象的列表。这些对象 - 比如学生和教师 - 必须有一些共同点,否则你不会尝试使用相同的方法来检索它们的列表。例如,您可能只想显示名称并使用ID作为密钥。
在这种情况下,我建议您定义一个接口,该接口具有您实际需要的Student,Teacher等通用属性,然后返回该接口类型的列表。在该方法中,您基本上将使用工厂模式的变体。
因此,您可以定义如下界面:
public interface INamedPerson
{
int ID { get; }
string FirstName { get; }
string LastName { get; }
}
让您的实体实现此界面。自动生成的实体(通常)是部分类,因此在您自己的新代码文件(而不是自动生成的代码文件本身)中,您可以执行以下操作:
public partial class Student : INamedPerson
{
public int ID
{
get
{
return StudentId;
}
}
}
和
public partial class Teacher : INamedPerson
{
public int ID
{
get
{
return TeacherId;
}
}
}
现在,您甚至可能不需要添加ID
属性(如果已有)。但是,如果每个类中的identity属性不同,则此适配器可以是实现所需接口的一种方法。
然后,对于方法本身,一个例子是:
public List<INamedPerson> MakeListOfType(Type type)
{
if (type == typeof(Student))
{
// Get your list of students. I'll just use a made-up
// method that returns List<Student>.
return GetStudentList().Select<Student, INamedPerson>(s => (INamedPerson)s)
.ToList<INamedPerson>();
}
if (type == typeof(Teacher))
{
return GetTeacherList().Select<Teacher, INamedPerson>(t => (INamedPerson)t)
.ToList<INamedPerson>();
}
throw new ArgumentException("Invalid type.");
}
现在,有一些方法可以改进这种模式。如果你有很多相关的类,你可能想要使用某种依赖注入框架。此外,您可能会注意到有很多重复的代码。您可以通过执行类似
之类的操作来传递函数(如GetStudentList
或GetTeacherList
)
public List<INamedPerson> GetListFromFunction<T>(Func<IEnumerable<T>> theFunction) where T : INamedPerson
{
return theFunction().Select<T, INamedPerson>(t => (INamedPerson)t).ToList<INamedPerson>();
}
当然,使用此函数再次要求传入的类型在编译时是已知的。但是,在某些时候,你将不得不决定一个类型,所以也许这是适当的时间。此外,您可以通过在方法调用时离开泛型类型来使您的生活变得更简单;只要传入一个不带参数的函数并返回IEnumerable
实现INamedPerson
的相同类型的对象,编译器就可以找出通用类型{{1}的用途}}