// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. <#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Runtime" #> <#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net46\System.Threading.Tasks.Extensions.dll" #> <#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net46\System.Linq.Async.dll" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Threading" #> <#@ import namespace="System.Threading.Tasks" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".cs" #> <# var nullableParameterNames = new[] { "comparer" }; var exclude = new[] { "ForEachAsync", "ForEachAwaitAsync", "ForEachAwaitWithCancellationAsync", "ToEnumerable", "ToAsyncEnumerable", "ToObservable", "AsAsyncEnumerable", "WithCancellation" }; var toQuotedImpl = default(Func); toQuotedImpl = (t, i, b) => { var name = t.Name; if (t.IsGenericType) { var genDef = t.GetGenericTypeDefinition(); name = genDef.Name.Substring(0, genDef.Name.LastIndexOf('`')); var genArgs = "<" + string.Join(", ", t.GetGenericArguments().Select(a => toQuotedImpl(a, i, false))) + ">"; if (b) { if (name == "Func" || name == "Action") { name = "Expression<" + name + genArgs + ">"; } else if (name == "IAsyncEnumerable" && i == 0) { name = "IAsyncQueryable" + genArgs; } else if (name == "IOrderedAsyncEnumerable" && i == 0) { name = "IOrderedAsyncQueryable" + genArgs; } else { name += genArgs; } } else { if (name == "Nullable") { name = genArgs.Substring(1, genArgs.Length - 2) + "?"; } else { name += genArgs; } } } else if (t.IsArray) { var elem = toQuotedImpl(t.GetElementType(), i, b); name = elem + "[]"; } else { if (t == typeof(int)) { name = "int"; } else if (t == typeof(long)) { name = "long"; } else if (t == typeof(float)) { name = "float"; } else if (t == typeof(double)) { name = "double"; } else if (t == typeof(decimal)) { name = "decimal"; } else if (t == typeof(bool)) { name = "bool"; } else if (t == typeof(object)) { name = "object"; } } return name; }; var toQuoted = new Func((t, i) => toQuotedImpl(t, i, true)); #> using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace System.Linq { public static partial class AsyncQueryable { <# // NOTE: Just including extension methods foreach (var m in typeof(AsyncEnumerable).GetMethods() .Where(m => m.IsStatic) .Where(m => !exclude.Contains(m.Name)) .Where(m => m.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), true)) .Where(m => { var p0 = m.GetParameters()[0].ParameterType; if (p0.IsGenericType) { var p0d = p0.GetGenericTypeDefinition(); return p0d == typeof(IAsyncEnumerable<>) || p0d == typeof(IOrderedAsyncEnumerable<>); } return false; }) .OrderBy(m => m.Name) .ThenBy(m => m.IsGenericMethod ? m.GetGenericArguments().Length : 0) .ThenBy(m => m.GetParameters().Length) .ThenBy(m => string.Join(", ", m.GetParameters().Select((p, i) => toQuoted(p.ParameterType, i) + " " + p.Name)))) { var genArgs = m.GetGenericArguments(); var ret = toQuoted(m.ReturnType, 0); var name = m.Name; if (genArgs.Length > 0) { name += "<" + string.Join(", ", genArgs.Select(a => a.Name)) + ">"; } var isParams = false; var lastParameterDefault = false; var parCount = m.GetParameters().Length; if (parCount != 0) { var lastParam = m.GetParameters().Last(); if (lastParam.IsDefined(typeof(ParamArrayAttribute), true)) { isParams = true; } if (lastParam.ParameterType == typeof(CancellationToken)) { lastParameterDefault = true; } } var pars = string.Join(", ", m.GetParameters().Select((p, i) => (i == parCount - 1 && isParams ? "params " : "") + toQuoted(p.ParameterType, i) + " " + p.Name + (i == parCount - 1 && lastParameterDefault ? " = default" : ""))); var quotedPars = string.Join(", ", m.GetParameters().Select((p, i) => "default(" + toQuoted(p.ParameterType, i) + ")")); if (m.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), true)) { pars = "this " + pars; } var mtd = "(MethodInfo)MethodBase.GetCurrentMethod()"; if (m.IsGenericMethod) { mtd = "(" + mtd + ").MakeGenericMethod(" + string.Join(", ", genArgs.Select(a => "typeof(" + a.Name + ")")) + ")"; } var provider = m.GetParameters()[0].Name + ".Provider"; var factory = ""; var rem = ""; var cast = ""; var quotedArgs = new List(); if (m.ReturnType.IsGenericType) { var td = m.ReturnType.GetGenericTypeDefinition(); if (td.Name.EndsWith("Task`1")) // NB: Covers Task and ValueTask { factory = "ExecuteAsync<" + toQuotedImpl(m.ReturnType.GetGenericArguments()[0], -1, false) + ">"; var last = m.GetParameters().Last(); if (last.ParameterType == typeof(CancellationToken)) { rem = ", " + last.Name; } else { rem = ", CancellationToken.None"; } } else if (td == typeof(IAsyncEnumerable<>) || td == typeof(IOrderedAsyncEnumerable<>)) { factory = "CreateQuery<" + toQuotedImpl(m.ReturnType.GetGenericArguments()[0], -1, false) + ">"; if (td == typeof(IOrderedAsyncEnumerable<>)) { cast = "(" + toQuoted(m.ReturnType, 0) + ")"; } } } var n = 0; foreach (var p in m.GetParameters()) { var pt = p.ParameterType; var add = false; if (pt.IsGenericType) { var ptd = pt.GetGenericTypeDefinition(); if (ptd == typeof(IAsyncEnumerable<>) || ptd == typeof(IOrderedAsyncEnumerable<>)) { if (n == 0) { quotedArgs.Add(p.Name + ".Expression"); } else { quotedArgs.Add("GetSourceExpression(" + p.Name + ")"); } add = true; } else if (ptd.Name.StartsWith("Func") || ptd.Name.StartsWith("Action")) { quotedArgs.Add(p.Name); add = true; } } if (!add) { quotedArgs.Add("Expression.Constant(" + p.Name + ", typeof(" + toQuoted(pt, -1) + "))"); } n++; } var expr = "Expression.Call(" + mtd + ", " + string.Join(", ", quotedArgs) + ")"; var infoofmtd = "InfoOf(() => AsyncQueryable." + name + "(" + quotedPars + "))"; var infoofexpr = "Expression.Call(" + infoofmtd + ", " + string.Join(", ", quotedArgs) + ")"; #> public static <#=ret#> <#=name#>(<#=pars#>) { <# var any = false; foreach (var p in m.GetParameters()) { if (!p.ParameterType.IsValueType && !p.ParameterType.IsGenericParameter && !nullableParameterNames.Contains(p.Name)) { any = true; #> if (<#=p.Name#> == null) throw new ArgumentNullException(nameof(<#=p.Name#>)); <# } } #> <# if (any) { #> <# } #> #if CRIPPLED_REFLECTION return <#=cast#><#=provider#>.<#=factory#>(<#=infoofexpr#><#=rem#>); #else return <#=cast#><#=provider#>.<#=factory#>(<#=expr#><#=rem#>); #endif } <# } #> } }