|
@@ -3,292 +3,13 @@
|
|
// See the LICENSE file in the project root for more information.
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
|
<#@ template debug="false" hostspecific="false" language="C#" #>
|
|
<#@ 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.Threading.Tasks.Extensions.dll" #>
|
|
<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net46\System.Linq.Async.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" #>
|
|
<#@ output extension=".cs" #>
|
|
<#
|
|
<#
|
|
|
|
+var asyncEnumerableType = typeof(AsyncEnumerable);
|
|
|
|
+var className = "AsyncQueryable";
|
|
var nullableParameterNames = new[] { "comparer" };
|
|
var nullableParameterNames = new[] { "comparer" };
|
|
var exclude = new[] { "ForEachAsync", "ForEachAwaitAsync", "ForEachAwaitWithCancellationAsync", "ToEnumerable", "ToAsyncEnumerable", "ToObservable", "AsAsyncEnumerable", "WithCancellation" };
|
|
var exclude = new[] { "ForEachAsync", "ForEachAwaitAsync", "ForEachAwaitWithCancellationAsync", "ToEnumerable", "ToAsyncEnumerable", "ToObservable", "AsAsyncEnumerable", "WithCancellation" };
|
|
-
|
|
|
|
-var toQuotedImpl = default(Func<Type, int, bool, string>);
|
|
|
|
-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<Type, int, string>((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<string>();
|
|
|
|
-
|
|
|
|
- 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
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-<#
|
|
|
|
-}
|
|
|
|
#>
|
|
#>
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
+<#@ include file="$(SolutionDir)\AsyncQueryableGenerator.t4" #>
|