您的AsQueryable<TClass> 应该将属性表达式作为参数,并且它需要具有以下签名:
public static IQueryable<TClass> AsQueryable<TClass>(this TClass obj, params Expression<Func<TClass, object>>[] propertyExpressions)
请注意,我们使用的是Func<TClass, object>,它是一个接受 TClass 作为输入并返回一个对象的函数。这使我们可以进行如下调用:
IQueryable<TClass> tClassQueryable = tClassObj.AsQueryable(x => x.Property1, x => x.Property2);
另外请注意,我没有偶然选择object 作为Func<TClass, object> 的TResult。由于函数委托的 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。