我有以下代码(示例):
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()方法并返回数据?我可以用反射做到这一点吗?你能救我吗?
答案 0 :(得分:22)
您可以使用反射来执行此操作,但是您还需要使用泛型,因为ToList()方法返回的列表类型对于每种实体类型都是不同的。
您可以通过反射访问属性获取器,如下所示:
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
匹配的属性。我将此作为练习: - )
答案 1 :(得分: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()并删除.ToList(),然后您将获得纯IQueryable,您可以进一步查询。