有没有办法在 运行 时间使用 codeDOM 生成的实体上调用通用存储库方法?

Is there a way to call generic repository methods on an entity that was generated at run time with codeDOM?

我正在使用 codeDOM 在 运行 时间生成我的实体 classes。我还有一个通用存储库来处理各种数据库功能。这是我的通用存储库中作为示例方法的 Insert 方法:

public void Insert<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity
{
    if (entity == null)
    {
        throw new ArgumentNullException("entity");
    }

    TEntity existing = Existing(entity);
    if (existing == null)
    {
        _context.Set<TEntity>().Add(entity);
        this._context.SaveChanges();
    }
}

下面是一些示例代码,说明我如何生成实体 class 以及如何使用 codeDOM 基于该实体 class 创建实体:

//Generate the fields of the new entity class
EntityGenerator.EntityFieldInfo entityField1 = new EntityGenerator.EntityFieldInfo("Name", typeof(string), RelationshipType.NoRelation);
EntityGenerator.EntityFieldInfo entityField2 = new EntityGenerator.EntityFieldInfo("Shape", typeof(string), RelationshipType.NoRelation);
ICollection<EntityGenerator.EntityFieldInfo> entityFieldList = new List<EntityGenerator.EntityFieldInfo> { entityField1, entityField2 };

// Create the new entity class using the fields established above 
// as well as the name of the entity (typeName = "Thing")
string typeName = "Thing";
EntityGenerator.CreateEntityClass(entityFieldList, typeName);
CompilerResults results = EntityGenerator.GetCompiledEntity(typeName);

// Create an entity instance based on the new entity class that was just created
Object newThing = EntityGenerator.CreateInstanceOfEntity(results, typeName);
SetObjectField(newEntity, "Name", "Box");
SetObjectField(newEntity, "Shape", "Cuboid");

如您所见,newThing(新实体实例)是一个Object类型。如果这是一个硬编码的实体 class 那么我可以说

Thing newThing;

但是 CodeDOM 创建的 Thing 实体不是硬编码的 class 所以我必须使用 Object 类型而不是 Thing 类型。这是一个问题,因为我使用的是通用存储库。假设我想将这个实体插入到数据库中。我想打电话给:

myRepository.Insert<Thing>(newThing);

但是,Thing 是在 运行 时由 CodeDOM 创建的,因此它不是 class,这意味着它不能进入​​ <> 内部。您可能已经注意到上面我的 Insert 方法中,TEntity 也是一个 IBusinessEntity。如果我尝试

myRepository.Insert<IBusinessEntity>(newThing);

我收到错误:

Argument type 'object' is not assignable to parameter type 'Models.IBusinessEntity'

如果我尝试不在 <> 中添加任何内容,就像这样:

myRepository.Insert(新事物);

我收到错误:

The type 'object' must be convertible to 'Models.IBusinessEntity' in order to use it as a parameter 'TEntity' in the generic method 'void Insert(TEntity)'.

有谁知道如何协调这个 codeDOM 生成的实体与通用存储库?反思有帮助吗?如果反射能以某种方式给我一个可以传递到 <> 中的 class 事物,那就太好了。另外我应该注意,我使用 CodeDOM 创建的所有实体都扩展了 IBusinessEntity。

我认为它很难实现,因为 EF 使用 DbContext 中包含的 DbSet 来创建映射。您认为如何创建它们?

无论如何,您不需要使用 EF 的类型,您可以经常使用 GetType。 在你的方法中(缺少 Existing(.) 但我认为是相似的)你可以使用

public void Insert(object entity)
{
    if (entity == null)
        throw new ArgumentNullException("entity");

    if (!(entity is IBusinessEntity))
        throw new ArgumentInvalidException("entity is not an IBusinessEntity");

    object existing = Existing(entity);
    if (existing == null)
    {
        _context.Set(entity.GetType()).Add(entity);
        this._context.SaveChanges();
    }

}

使用 Set<> 或 Set(.) 我很确定 EF 将搜索从 DbContext 中包含的 DbSet 开始创建的映射。我不记得确切的异常,但我播种它的时间不同(当我使用 DbContext.Set(myEntityType)).