protected override ExpressionBody Transform(CallExpression lx)
        {
            if (!_nameResolver.TryResolveFunctionName(lx.OperatorName, out var m))
            {
                throw new ArgumentException($"The function name `{lx.OperatorName}` was not recognized.");
            }

            var parameterCount = m.GetParameters().Count(pi => pi.ParameterType == typeof(LogEventPropertyValue));

            if (parameterCount != lx.Operands.Length)
            {
                throw new ArgumentException($"The function `{lx.OperatorName}` requires {parameterCount} arguments.");
            }

            var operands = lx.Operands.Select(Transform).ToList();

            // `and` and `or` short-circuit to save execution time; unlike the earlier Serilog.Filters.Expressions, nothing else does.
            if (Operators.SameOperator(lx.OperatorName, Operators.RuntimeOpAnd))
            {
                return(CompileLogical(LX.AndAlso, operands[0], operands[1]));
            }

            if (Operators.SameOperator(lx.OperatorName, Operators.RuntimeOpOr))
            {
                return(CompileLogical(LX.OrElse, operands[0], operands[1]));
            }

            if (m.GetParameters().Any(pi => pi.ParameterType == typeof(StringComparison)))
            {
                operands.Insert(0, LX.Constant(lx.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
            }

            return(LX.Call(m, operands));
        }