如何使用反射创建具有已定义参数的通用对象

本文关键字:参数 对象 定义 反射 何使用 创建 | 更新日期: 2023-09-27 17:56:04

我正在尝试为实体框架存储库和 UnitOfWork 类构建一个通用基类。 我按基本存储库类定义如下:

public class EntityRepository<CContext, TEntity>
    where TEntity : class
    where CContext : DbContext
{
     protected readonly CContext _DbContext;
     protected readonly DbSet<TEntity> _DbSet;
     public EntityRepository(CContext context)
     {
         this._DbContext = context;
         this._DbSet = context.Set<TEntity>();
     }
     // Implementation details go here
}

我可以创建存储库的类型化实例,如下所示:

var ctx = new ProductContext();
var db = new EntityRepository<ProductContext, Product>(ctx);

尽管在实践中,将为数据上下文中的每个类创建一个特定于类型的存储库,例如......

public class ProductDb
    : EntityRepository<ProductContext, Product>
{
    public ProductDb(ProductContext context)
        : base(context)
    {
    }

}

这一切似乎都按预期工作。 我的问题在于我的通用 UnitOfWork 基类。 以前,我已经在 UnitOfWork 实现中手动定义了每个存储库属性,但我想通过使用哈希表和反射来自动化此操作(类似于 Long Le 博客中描述的)。

public class UnitOfWork<CContext>
    where CContext : DbContext
{
    protected readonly CContext _Context;
    protected readonly Hashtable _Repositories;
    public UnitOfWork(CContext context)
    {
       this._Context = context;
       this._Repositories = new Hashtable();
    }
    public EntityRepository<CContext, TEntity> Repository<TEntity>()
        where TEntity : class
    {
        var type = typeof(TEntity).Name;
        if (!_Repositories.ContainsKey(type))
        {
            var repositoryType = typeof(EntityRepository<CContext, TEntity>);
            var repositoryInstance = Activator.CreateInstance(
                repositoryType.MakeGenericType(typeof(TEntity))
             );
            _Repositories.Add(type, repositoryInstance);
        }
        return (EntityRepository<CContext, TEntity>)_Repositories[type];
    }
}

当我运行此代码时,它失败并显示错误消息:

Product 不是 GenericTypeDefinition.MakeGenericType

谁能指出我解决这个问题的正确方向,或者以另一种方式提出问题,如何使用反射创建我的 EntityType 的新实例?

谢谢。

如何使用反射创建具有已定义参数的通用对象

那是因为你得到了错误的类型。这是错误的,因为它获取泛型实例的类型。

var repositoryType = typeof(EntityRepository<CContext, TEntity>);

请改用此选项来获取泛型的类型。

var repositoryType = typeof(EntityRepository<,>);

你还需要改变这个

var repositoryInstance = Activator.CreateInstance(
                repositoryType.MakeGenericType(typeof(CContext>,typeof(TEntity))
             );