private static LambdaExpression ReplaceEnumerables(IConnectQlFunctions functions, string name, LambdaExpression lambda) { while (lambda.Parameters.Any(p => p.Type.HasInterface(typeof(IEnumerable <>)) && p.Type != typeof(string))) { var replacements = lambda.Parameters .Select(p => new { Original = p, ReplaceBy = p.Type.HasInterface(typeof(IEnumerable <>)) && p.Type != typeof(string) ? Expression.Parameter(typeof(IAsyncEnumerable <>).MakeGenericType(p.Type.GenericTypeArguments[0]), p.Name) : p, }) .ToArray(); var enumerableParameter = replacements.First(p => p.ReplaceBy.Type.HasInterface(typeof(IAsyncEnumerable <>))); functions.Logger?.Warning($"Parameter {enumerableParameter.Original.Name} of function {name} is an IEnumerable<T>, this reduces performance, consider using IAsyncEnumerable<T>."); lambda = Expression.Lambda( GenericVisitor.Visit( (MethodCallExpression e) => e.Object != enumerableParameter.Original && !e.Arguments.Contains(enumerableParameter.Original) ? null : TaskExpression.Task( Expression.Call( ConnectQlFunctionsExtensions.ApplyEnumerableFunction.MakeGenericMethod(enumerableParameter.Original.Type.GenericTypeArguments[0], e.Type), enumerableParameter.ReplaceBy, Expression.Lambda(e, enumerableParameter.Original))), lambda.Body), replacements.Select(r => r.ReplaceBy)); } return(lambda); }
public static IFunctionRegistration AddWithoutSideEffects <TResult>([NotNull] this IConnectQlFunctions functions, string key, Expression <Func <TResult> > function) { var descriptor = new FunctionDescriptor(key, false, ConnectQlFunctionsExtensions.ReplaceEnumerables(functions, key, function)); return(new FunctionRegistration(descriptor, functions.AddFunction(key, descriptor))); }
public static IFunctionRegistration6 AddWithSideEffects <TArgument1, TArgument2, TArgument3, TArgument4, TArgument5, TArgument6, TResult>([NotNull] this IConnectQlFunctions functions, string key, Expression <Func <TArgument1, TArgument2, TArgument3, TArgument4, TArgument5, TArgument6, TResult> > function) { var descriptor = new FunctionDescriptor(key, true, ConnectQlFunctionsExtensions.ReplaceEnumerables(functions, key, function)); return(new FunctionRegistration(descriptor, functions.AddFunction(key, descriptor))); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionRegistration"/> class. /// </summary> /// <param name="descriptor"> /// The descriptor. /// </param> /// <param name="functions"> /// The functions. /// </param> internal FunctionRegistration(FunctionDescriptor descriptor, IConnectQlFunctions functions) { this.descriptor = descriptor; this.functions = functions; }