2012-09-17 202 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,你可以進一步查詢。