15

我有以下代码(示例):

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() 方法并返回数据?我可以使用反射来做到这一点吗?

4

2 回答 2

23

您可以使用反射来完成此操作,但是您还需要使用泛型,因为 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. 我把它作为练习:-)

于 2012-09-17T08:16:21.383 回答
1

您可以使用这样的代码

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,您可以进一步查询。

于 2017-10-31T11:35:12.030 回答