2012-09-17 206 views
13

获得实体我有以下代码(例如):实体框架 - 按名称

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

我想避免这种样品中切换。如何通过名称找到所需的实体类,调用ToList()方法并返回数据?我可以使用反射吗?你可以帮我吗?

回答

22

您可以使用反射来做到这一点,但是您还需要使用泛型,因为ToList()方法返回的列表类型对于每个实体类型都是不同的。

你可以像这样通过反射访问属性的getter:

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

[ClassNameOfContext]是CTX是一个实例的类的名称。这是不是从你的代码显而易见的,但你知道它:-)

的问题是,enumerable将是一个object并已被强制转换为IEnumerable<EntityType>,其中EntityType是实体您正在访问的类型。换句话说,这取决于你传递的名字。如果您使用泛型来确定类型,您将能够正确地投射对象,并且不必返回dynamic甚至。

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

,并从上述变换行:

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

在这里你去!

附录:您可以想象,也可以摆脱字符串参数 - 如果可能,应避免使用字符串中的类型或属性名称,因为它不是类型安全的。编译器无法识别它,并且IDE功能(如重构)无法解释它。这里的问题是属性名称通常是实体类型名称的复数形式。但是,您可以使用反射来查找类型与TEntity匹配的属性。在我离开这个作为一个练习:-)

+0

如何使用反射来做到这一点? ToList返回的类型无关紧要,因为GetData返回类型是动态的 - 所以它可以是任何类型 – user1209216

+0

@ user1209216 - 我更新了我的答案。 – chiccodoro

+0

@ user1209216 - 您使用动态来解决问题,因为在我看来。应该有意识地使用'dynamic'关键字。它有非常具体的使用情况,可以合理使用,但在您的情况下,您完全可以强制键入返回类型。这是首选的方法。 – chiccodoro

0

您可以使用这样的代码

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

要调用这样的:

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

您可以删除.AsNoTracking()和remove .ToList (),那么你将得到纯粹的IQueryable,你可以进一步查询。