さまざまな SO 投稿、特にこのブログAndAlso
(ではなく使用するように修正And
) からの情報を使用して、同様に型指定された linq 式を 1 つの述語に組み合わせることができました。しかし今、一方が他方への入力である 2 つの式を結合したいと考えています。これが完全に展開されたオリジナルExpression
です。
private Expression<Func<T, bool>> ExpressionIsNamed(IEnumerable<EntityName> AccessorNames)
{
// works
Expression<Func<T, bool>> Texpr = x => x.Security.Readers.Any(n => AccessorNames.ToStringArray().Contains(n.Text));
return Texpr;
}
DB ドライバーはツリーをたどってネイティブ呼び出しに変換する必要があるため、Compile() を使用して結合することはできません。
Any()
以下は、上記の呼び出しと組み合わせたい関数です。最終出力 Expression は型Expression<Func<T, bool>>
である必要があり、これに渡す必要がありx.Security.Readers
ます。
public static Expression<Func<IEnumerable<EntityName>,bool>> AccessCheckExpression(IEnumerable<EntityName> AccessorNames)
{
return accessList => accessList.Any(n => AccessorNames.ToStringArray().Contains(n.Text));
}
私はこれまでのところ持っていますが、スワップアウトaccessList =>
して単一の式accessCheck
で使用する方法を見つけるのに苦労しています。accessList
これまでのところ、これがあります。
private Expression<Func<T, bool>> ExpressionIsNamed(IEnumerable<EntityName> AccessorNames)
{
Expression<Func<T, IEnumerable<EntityName>>> accessList = (T x) => x.Security.Readers;
Expression<Func<IEnumerable<EntityName>, bool>> accessCheck = SecurityDescriptor.AccessCheckExpression(AccessorNames);
// Combine?
Expression<Func<T, bool>> Texpr = ??? accessCheck + accessList ???
return Texpr;
}
[アップデート]
だから私はもう少し先に進んでいます。
class ParameterUpdateVisitor : System.Linq.Expressions.ExpressionVisitor
{
private ParameterExpression _oldParameter;
private ParameterExpression _newParameter;
public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (object.ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
static Expression<Func<T, bool>> UpdateParameter<T>(
Expression<Func<T, IEnumerable<EntityName>>> expr,
ParameterExpression newParameter)
{
var visitor = new ParameterUpdateVisitor(expr.Parameters[0], newParameter);
var body = visitor.Visit(expr.Body);
return Expression.Lambda<Func<T, bool>>(body, newParameter);
}
その後、コンパイルできます。
UpdateParameter(accessList, accessCheck.Parameters[0]);
これらの提案に感謝しますInvoke()
が、私の推測では、彼らが MongoDB ドライバーにたどり着くまでには、InvocationExpression
. ただし、Invoke
上記の両方と私のコードはまったく同じように失敗します。つまり;
System.ArgumentException: Expression of type
'System.Func`2[MyLib.Project,System.Collections.Generic.IEnumerable`1[MyLib.EntityName]]'
cannot be used for parameter of type
'System.Collections.Generic.IEnumerable`1[MyLib.EntityName]'
x.Security.Readers
したがって、暗黙のパラメーターは単純な古いものとは異なるタイプであるように見えますIEnumerable<EntityName>