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

时间:2014-04-02 12:20:00

标签: c# generics reflection

我正在尝试为Entity Framework Repository和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's Blog中描述的那样)来自动化它

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];
    }
}

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

  

产品不是GenericTypeDefinition.MakeGenericType

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

感谢。

1 个答案:

答案 0 :(得分:1)

那是因为你的错误类型。这是错误的,因为它获得了通用实例的类型。

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

使用它来获取通用的类型。

var repositoryType = typeof(EntityRepository<,>);

您还需要更改此

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