作为参数的 Linq 表达式

2024-03-07

我想打电话给IQueryable<T>方法来自我的存储库,但我想在我的 ORM 中急切地加载子对象。为了将持久性逻辑保留在持久性层中,我想传递表示我想要急切加载的属性的表达式列表。

My IRepository<TClass>方法如下所示:

IQueryable<TClass> AsQueryable();

我想让它看起来像:

IQueryable<TClass> AsQueryable(params --something here--[] includeProperties);

...这样我就可以这样称呼它:

var q = myFooRepository.AsQueryable(x => x.Property1, x => x.Property2, ...);

并在后端反汇编委托以急切地加载指定的属性。

我应该为此使用什么?


Your AsQueryable<TClass>应该有属性表达式作为参数,并且需要具有以下签名:

public static IQueryable<TClass> AsQueryable<TClass>(this TClass obj, params Expression<Func<TClass, object>>[] propertyExpressions)

请注意,我们正在使用Func<TClass, object>这是一个接受 Class 作为输入并返回一个对象的函数。这允许我们进行如下调用:

IQueryable<TClass> tClassQueryable = tClassObj.AsQueryable(x => x.Property1, x => x.Property2);

另请注意,我没有选择object作为结果Func<TClass, object>偶然。由于函数委托的 TResult 泛型参数是协变的,因此即使具有不同的属性类型,我们也可以传递表达式。因此,上例中的 Property1 和 Property2 不需要是同一类型。

我想,关于你的问题,就是这样,但这里有一些额外的内容:

如果您偶然需要评估传递的表达式以便将它们与 ORM 一起使用(例如,您只需要属性名称,但希望将它们作为表达式传递以避免硬编码名称并保留编译时检查),您将需要像这样的东西:

  public static IQueryable<TClass> AsQueryable<TClass>(this TClass obj, params Expression<Func<TClass, object>>[] propertyExpressions)
    {
        foreach (var propertyExpression in propertyExpressions)
        {
            MemberExpression memberExpression = propertyExpression.Body as MemberExpression;

            if (memberExpression == null)
            {
                // this is needed for value types properties.
                UnaryExpression unaryExpression = (UnaryExpression)propertyExpression.Body;
                memberExpression = unaryExpression.Operand as MemberExpression;
            }

            if (memberExpression == null)
                throw new ArgumentException(string.Format("Expression '{0}' is not a member expression.", propertyExpression.ToString()));

            PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
            if (propertyInfo == null)
                throw new ArgumentException("MemberExpression.Member is not a PropertyInfo.");


            // at this point we have PropertyInfo which you can use with your OR Mapper to further implement logic which will eager load the property
            // e.g. property name can be retrieved with:
            string propertyName = propertyInfo.Name;

            // do your ORM stuff here
        }
    }

上面的代码确保传递的表达式是属性表达式,并从中提取 PropertyInfo。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

作为参数的 Linq 表达式 的相关文章

随机推荐