2012-09-17 23 views
13

tengo el siguiente código (ejemplo):marco Entidad - conseguir entidad por su nombre

public dynamic GetData(string name) 
{ 
    using(var ctx = GetObjectContext()) 
    { 
     switch (name) 
     { 
     case "entity1": 
      return ctx.entity1.ToList(); 
     case "entity2": 
      return ctx.entity2.ToList(); 
     ...... 
     default: 
      return null; 
     } 
    } 
} 

quiero evitar interruptor en esta muestra. ¿Cómo puedo encontrar la clase de entidad necesaria por nombre, llamar al método ToList() y devolver datos? ¿Puedo hacer esto usando la reflexión? ¿Me puedes ayudar?

Respuesta

22

Puede hacerlo utilizando la reflexión, sin embargo, también necesitará usar genéricos porque el tipo de lista devuelta por el método ToList() es diferente para cada tipo de entidad.

puede acceder a una propiedad de captador través de la reflexión de este modo:

var enumerable = typeof([ClassNameOfContext]).GetProperty(name).GetValue(ctx, null); 

Mientras [ClassNameOfContext] es el nombre de la clase que CTX es una instancia de. Esto no es obvio a partir de su código, pero sabes que :-)

El problema es que enumerable habrá un object y tiene que ser moldeado a IEnumerable<EntityType> donde EntityType es el tipo de entidad que está accediendo. En otras palabras, depende del nombre que está pasando. Si usa genéricos para determinar el tipo, podrá lanzar el objeto correctamente y no tiene que devolver un dynamic par.

public TEntity Get<TEntity>(string name) 
{ 
    ... 

y transformar la línea de arriba:

var enumerable = (IEnumerable<TEntity>)(typeof([ClassNameOfContext]).GetProperty(name).GetValue(ctx, null)); 
return enumerable.ToList(); 

Aquí tienes!

Adición: Se podría, posiblemente, deshacerse del parámetro de cadena, se deben evitar nombres de tipos o propiedades en cadenas siempre que sea posible, ya que no es seguro. El compilador no lo reconoce y las funciones IDE, como las refactorizaciones, no lo tienen en cuenta. El problema aquí es que los nombres de propiedad suelen ser la forma pluralizada de los nombres de tipo de entidad. Pero podría usar el reflejo para encontrar la propiedad cuyo tipo coincida con el TEntity. Dejo esto como un ejercicio :-)

+0

¿Cómo puedo hacer esto usando la reflexión? El tipo devuelto por ToList no importa, porque el tipo de devolución GetData es dinámico, por lo que puede ser de cualquier tipo – user1209216

+0

@ user1209216 - Actualicé mi respuesta. – chiccodoro

+0

@ user1209216 - está utilizando Dynamic para solucionar un problema como me parece. La palabra clave 'dynamic' debe usarse conscientemente. Tiene sus casos de uso muy específicos en los que es razonable usarlos, pero en su caso puede escribir con fuerza su tipo de devolución. Esta es la forma preferida de ir. – chiccodoro

0

Puede usar un código como éste

private IEnumerable<TEntity> GetList<TEntity>(string connectionString, Func<object, T> caster) 
{ 
    using (var ctx = new DbContext(connectionString)) 
    { 
     var setMethod = ctx.GetType().GetMethod("Set").MakeGenericMethod(typeof(T)); 

     var querable = ((DbSet<object>)setMethod 
     .Invoke(this, null)) 
     .AsNoTracking() 
     .AsQueryable(); 

     return querable 
      .Select(x => caster(x)) 
      .ToList(); 
    } 
} 

Para llamar así:

var branchList = GetList<Branch>("connectionStringName", x => (Branch)x); 

Puede eliminar .AsNoTracking() y retire .ToList(), entonces obtendrá IQueryable puro que puede consultar más.

Cuestiones relacionadas