如何通过使用类型名称来实例化泛型类?
Posted
技术标签:
【中文标题】如何通过使用类型名称来实例化泛型类?【英文标题】:How to instantiate a generic class by using its type name? 【发布时间】:2011-10-11 02:53:34 【问题描述】:在我的项目(.NET 3.5)中,我得到了许多这样的 DAO:(每个实体一个)
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);
【问题讨论】:
【参考方案1】:如果您使用泛型并且不想为每个实体类型实现特定的 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'未定义或导入'我应该导入什么?
要使dynamic
工作,需要为.NET 4 编译项目并且需要引用程序集Microsoft.CSharp
和System.Core
。
这是个问题,解决方案必须针对 .NET 3.5。因此,我将使用Object
并用dao.dao.GetType().GetMethod("getAll").Invoke(dao, null)
调用它,而不是使用dynamic
。但在第一行,Type entityType = Type.GetType("Entities.Product");
返回 null,Entities
被引用。怎么了?
Type.GetType
需要一个程序集限定名称。或者,您可以使用Assembly.GetType
(在特定程序集中搜索类型)。关于object
和dynamic
,您可能希望您的AbstractDAO<>
实现一个提供GetAll
方法的简单接口。然后,您可以将实例强制转换到此接口。这比通过反射进行的后期绑定调用更有效,更不容易出错。【参考方案2】:
试试:
Type d1 = typeof(AbstractDAO<>);
Type[] typeArgs = Type.GetType("ProductDAO");
Type constructed = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(constructed);
o.GetType().GetMethod("getAll").Invoke();
【讨论】:
以上是关于如何通过使用类型名称来实例化泛型类?的主要内容,如果未能解决你的问题,请参考以下文章