我正在使用Entity Framework和LINQ。我想在GridViews的“帮助器”类中创建一个可重用的方法。
该方法将根据传递的实体类型将DataSource作为实体列表返回。
因此GridView1将显示[Entity1],因此调用将如下所示:
GridView1.DataSource = helperClass.GetDataSource(new Entity1());
注意*如果我应该在方法中传递我想要的实体类型作为字符串,我会打开提示。我只是不想在这个方法可以返回的~40个实体类型之间使用切换案例
可重用的方法很简单,看起来类似于:
public static object GetDataSource(object type)
{
using (DatabaseContext dc = new DatabaseContext())
{
if (dc.[how do I get the entity type here].Count() > 0)
{
var modelList = dc.[how do I get the entity type here also].ToList();
}
}
}
这听起来很傻,但显然我无法做到:
var modelList = dc.(type.GetType()).ToList();
但这基本上就是我想要完成的事情。
答案 0 :(得分:0)
如果要在编译时绑定类型,可以将类型作为泛型参数传递,并使用以下类型的方法:
public DbSet<T> GetDataSource<T>()
{
var targetType = typeof(DbSet<T>);
return _db
.GetType()
.GetMethods()
.Where( m => m.ReturnType == targetType)
.Single()
.Invoke(_db, null) as DbSet<T>;
}
它是如何工作的?好吧,我们不知道返回正在请求的实体的方法的名称,但我们知道返回类型必须是DbSet<T>
。因此,我们扫描DatabaseContext以获取返回该类型的任何方法,并调用它。这假设只有一种方法具有该返回类型。
如果您需要真正的运行时绑定(您无法提供<T>
参数),则可以使用此类方法。请注意,返回类型只是一般IEnumerable
,因为如果在编译时未知,则无法使用特定的返回类型。如果需要,您可以随时将其强制转换为DbSet<T>
。
public IEnumerable GetDataSource(Type type)
{
var targetType = typeof(DbSet<>).MakeGenericType(new Type[] { type });
return _db
.GetType()
.GetMethods()
.Where( m => m.ReturnType == targetType)
.Single()
.Invoke(_db, null) as IEnumerable;
}
这是一个完整的例子。请注意,我删除了EF对象,但此示例仍应使用真实的DbSet
和DatabaseContext
。
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public class Program
{
public class DbSet<T> : List<T>
{
}
public class User
{
public string Name { get; set; }
public override string ToString()
{
return "User " + Name;
}
}
public class Transaction
{
public decimal Amount { get; set; }
public override string ToString()
{
return "Transaction " + Amount.ToString("0.00");
}
}
public class DatabaseContext
{
public DbSet<User> GetUsers()
{
return new DbSet<User>()
{
new User { Name = "Bob" },
new User { Name = "Alice" }
};
}
public DbSet<Transaction> GetTransactions()
{
return new DbSet<Transaction>()
{
new Transaction { Amount = 12.34M },
new Transaction { Amount = 56.78M }
};
}
}
public class HelperClass
{
private readonly DatabaseContext _db;
public HelperClass(DatabaseContext db)
{
_db = db;
}
public DbSet<T> GetDataSource<T>()
{
var targetType = typeof(DbSet<T>);
return _db
.GetType()
.GetMethods()
.Where( m => m.ReturnType == targetType)
.Single()
.Invoke(_db, null) as DbSet<T>;
}
public IEnumerable GetDataSource(Type type)
{
var targetType = typeof(DbSet<>).MakeGenericType(new Type[] { type });
return _db
.GetType()
.GetMethods()
.Where( m => m.ReturnType == targetType)
.Single()
.Invoke(_db, null) as IEnumerable;
}
}
public static void Main()
{
var helperClass = new HelperClass(new DatabaseContext());
foreach (var u in helperClass.GetDataSource<User>())
{
Console.WriteLine(u);
}
foreach (var t in helperClass.GetDataSource(typeof(Transaction)))
{
Console.WriteLine(t);
}
}
}
输出:
User Bob
User Alice
Transaction 12.34
Transaction 56.78
答案 1 :(得分:0)
这种方法不合理,我最终将GridView的数据源存储在SessionState变量中。节省了每次回发都需要重新查询DataSource的麻烦(如果我在重新查询时必须跟踪订单号,可能会变得很乏味。相反,sessionstate变量会保持排序顺序)