我有ParentItem
s应该应用安全修整。
因此,SecurityTrimmingExpressionFactory
会为父元素构建Expression<Func<ParentItem, bool>>
:
SecurityTrimmingExpressionFactory
public static Expression<Func<ParentItem, bool>> CreateTrimming(currentUser)
{
return parentItem => parentItem.OwnerId == currentUser.Id;
}
在我的WebAPI控制器中,我希望接收父元素的子项。 正常的方式我会像这样写
WebAPI控制器(获取)
return Entities.ChildItems.Where(c => c.parentId == <some id>);
完全没问题,但没有安全修整。
如果我想在此处应用我的安全修整(目前我正在使用LinqKit使用父项构建表达式树)
带有修剪的WebAPI控制器(获取)
var expr = TrimmingExpressionsFactory.CreateParentTrimming(this.CurrentUser);
return Entities.ChildItems
.AsExpandable()
.Where(childItem => expr.Invoke(childItem.ParentItem)
.Where(c => c.parentId == <some id>)
);
一切正常。
现在问题是在当前环境中禁止使用外部库(如LinqKit)(在我看来:错误的决定;))。 是否有另一种方法没有外部库来扩展或使用dependend Entities调用查询表达式?
已经尝试使用.AsEnumerable()
解决此问题(通常在网络中发现这是一种解决方法),但对于大型数据集来说,这不是一个可接受的解决方案。
答案 0 :(得分:1)
您可以使用我对Define part of an Expression as a variable in c#:
的回答中的小助手实用程序public static class ExpressionUtils
{
public static Expression<Func<TOuter, TResult>> Bind<TOuter, TInner, TResult>(this Expression<Func<TOuter, TInner>> source, Expression<Func<TInner, TResult>> resultSelector)
{
var body = new ParameterExpressionReplacer { source = resultSelector.Parameters[0], target = source.Body }.Visit(resultSelector.Body);
var lambda = Expression.Lambda<Func<TOuter, TResult>>(body, source.Parameters);
return lambda;
}
public static Expression<Func<TOuter, TResult>> ApplyTo<TInner, TResult, TOuter>(this Expression<Func<TInner, TResult>> source, Expression<Func<TOuter, TInner>> innerSelector)
{
return innerSelector.Bind(source);
}
class ParameterExpressionReplacer : ExpressionVisitor
{
public ParameterExpression source;
public Expression target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == source ? target : base.VisitParameter(node);
}
}
}
示例中的用法是:
var filter = TrimmingExpressionsFactory.CreateParentTrimming(this.CurrentUser)
.ApplyTo((ChildItem childItem) => childItem.ParentItem);
return Entities.ChildItems
.Where(filter)
.Where(c => c.parentId == <some id>)
);