jeudi 18 juin 2015

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

I am using codeDOM to generate my entity classes at run time. I also have a generic repository to deal with various DB functionality. Here is the Insert method as an example method in my generic repository:

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();
    }
}

Here is some example code of how I generate an entity class and how to create an entity based on that entity class using codeDOM:

//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");

As you can see, newThing (the new entity instance) is an Object type. If this was a hardcoded entity class then I could just say

Thing newThing;

But the Thing entity created by CodeDOM isn't a hardcoded class so I have to use type Object instead of type Thing. This is a problem because I am using a generic repository. Let's say I want to insert this entity into the database. I would like to call:

myRepository.Insert<Thing>(newThing);

However, Thing was just created by CodeDOM at run time, so it isn't a class, which means it can't go inside the <>. You may have noticed above in my Insert method, TEntity is also an IBusinessEntity. If I try

myRepository.Insert<IBusinessEntity>(newThing);

I get the error:

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

If I try without anything inside the <>, like this:

myRepository.Insert(newThing);

I get the error:

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)'.

Does anyone know how I can reconcile this codeDOM generated entity with a generic repository? Could reflection help? It would be nice if reflection could somehow give me a class of Thing which could be passed into the <>. Also I should note that all entities I create with CodeDOM extend IBusinessEntity.





Aucun commentaire:

Enregistrer un commentaire