如何通过使用类名来实例化一个泛型类?

4
在我的项目(.NET 3.5)中,我有很多像这样的DAOs:(每个实体都有一个)
public class ProductDAO : AbstractDAO<Product> 
{...}

我需要创建一个函数,它将接收DAO的名称或其实体的名称(无论您认为哪个更好),并运行DAO的“getAll()”函数。就像这段代码仅针对一个实体执行的操作一样:

ProductDAO dao = new ProductDAO();
dao.getAll();

我刚接触C#,如何使用反射来实现这个功能?

类似这样:

String entityName = "Product";
AbstractDAO<?> dao = new AbstractDAO<entityName>()
dao.getAll();

编辑

我忘记了一个细节,这是getAll()的返回方式:

IList<Product> products = productDao.getAll();

所以我还需要在列表上使用反射。如何做?
解决方案
Type daoType = typeof(AbstractDAO<>).Assembly.GetType("Entities.ProductDAO");
Object dao = Activator.CreateInstance(daoType);
object list = dao.GetType().GetMethod("getAll").Invoke(dao, null);
2个回答

8

如果你正在使用泛型,并且不想为每个实体类型实现特定的DAO,你可以使用以下代码:

Type entityType = typeof(Product); // you can look up the type name by string if you like as well, using `Type.GetType()`
Type abstractDAOType = typeof(AbstractDAO<>).MakeGenericType(entityType);
dynamic dao = Activator.CreateInstance(abstractDAOType); 
dao.getAll();

否则,只需使用计算出的DAO名称进行Type.GetType()操作(假设您遵循某种名称约定)。

dao.getAll() 中,我遇到了一个找不到的引用错误:`预定义类型 'Microsoft.CSharp.RuntimeBinder.Binder' 未定义或未导入'。我应该导入什么? - GxFlint
为了让 dynamic 正常工作,项目需要编译为 .NET 4,并且需要引用 Microsoft.CSharpSystem.Core 这两个程序集。 - Lucero
这是一个问题,解决方案必须适用于.NET 3.5。 因此,我将使用Object而不是dynamic,并使用dao.dao.GetType().GetMethod("getAll").Invoke(dao, null)进行调用。但在第一行中,Type entityType = Type.GetType("Entities.Product");返回null,Entities已被引用。出了什么问题? - GxFlint
1
Type.GetType 需要一个程序集限定名称。或者,您可以使用 Assembly.GetType(它在特定程序集中搜索类型)。关于 objectdynamic,您可能希望让您的 AbstractDAO<> 实现一个简单的接口,该接口提供 GetAll 方法。然后,您可以将实例转换为此接口。这比通过反射进行后期绑定调用更有效率且更少出错。 - Lucero

3

尝试:

Type d1 = typeof(AbstractDAO<>);
Type[] typeArgs = {Type.GetType("ProductDAO")};
Type constructed = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(constructed);

o.GetType().GetMethod("getAll").Invoke();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接