瀏覽代碼

Use cached refletion info for AsyncQueryable[Ex].

Bart De Smet 6 年之前
父節點
當前提交
905f456e37

+ 321 - 0
Ix.NET/Source/AsyncQueryableGenerator.t4

@@ -0,0 +1,321 @@
+<#@ assembly name="System.Core" #>
+<#@ assembly name="System.Runtime" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Threading" #>
+<#@ import namespace="System.Threading.Tasks" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#
+var infoFieldNames = new Dictionary<string, int>();
+
+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 <#=className#>
+    {
+<#
+// NOTE: Just including extension methods
+foreach (var m in asyncEnumerableType.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 infoName = m.Name;
+    var infoTypeArgs = "";
+    var infoToGeneric = "";
+    var infoMakeGeneric = "";
+    var infoGenArgs = "";
+
+    if (genArgs.Length > 0)
+    {
+        infoName += "__" + string.Join("_", genArgs.Select(a => a.Name));
+        infoTypeArgs = "(" + string.Join(", ", genArgs.Select(a => "Type " + a.Name)) + ")";
+        infoToGeneric = ".GetGenericMethodDefinition()";
+        infoMakeGeneric = ".MakeGenericMethod(" + string.Join(", ", genArgs.Select(a => a.Name)) + ")";
+        infoGenArgs = "<" + string.Join(", ", genArgs.Select(_ => "object")) + ">";
+    }
+
+    infoName += "__" + parCount + "__";
+
+    int infoNameCount;
+    if (!infoFieldNames.TryGetValue(infoName, out infoNameCount))
+    {
+        infoNameCount = 0;
+    }
+
+    var infoNameId = infoNameCount++;
+
+    infoFieldNames[infoName] = infoNameCount;
+
+    infoName += infoNameId;
+
+    var infoSignature = string.Join(", ", m.GetParameters().Select((p, i) => toQuoted(p.ParameterType, i)).Concat(new[] { toQuoted(m.ReturnType, 0) }));
+
+    foreach (var genArg in genArgs)
+    {
+        infoSignature = infoSignature.Replace(genArg.Name, "object");
+    }
+
+    var mtd = infoName;
+
+    if (m.IsGenericMethod)
+    {
+        mtd += "(" + 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) + ")";
+#>
+        private static MethodInfo s_<#=infoName#>;
+        
+        private static MethodInfo <#=infoName#><#=infoTypeArgs#> =>
+            (s_<#=infoName#> ??
+            (s_<#=infoName#> = new Func<<#=infoSignature#>>(<#=m.Name#><#=infoGenArgs#>).GetMethodInfo()<#=infoToGeneric#>))<#=infoMakeGeneric#>;
+
+        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)
+{
+#>
+
+<#
+}
+
+#>
+            return <#=cast#><#=provider#>.<#=factory#>(<#=expr#><#=rem#>);
+        }
+
+<#
+}
+#>
+    }
+}

+ 2 - 2
Ix.NET/Source/Directory.build.targets

@@ -2,10 +2,10 @@
 
 
   <!-- This props all need to be set in targets as they depend on the values set earlier -->
   <!-- This props all need to be set in targets as they depend on the values set earlier -->
   <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.0'">
   <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.0'">
-    <DefineConstants>$(DefineConstants);NO_ARRAY_EMPTY;NO_CODE_COVERAGE_ATTRIBUTE;CRIPPLED_REFLECTION</DefineConstants>
+    <DefineConstants>$(DefineConstants);NO_ARRAY_EMPTY;NO_CODE_COVERAGE_ATTRIBUTE</DefineConstants>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.4'">
   <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.4'">
-    <DefineConstants>$(DefineConstants);NO_CODE_COVERAGE_ATTRIBUTE;CRIPPLED_REFLECTION</DefineConstants>
+    <DefineConstants>$(DefineConstants);NO_CODE_COVERAGE_ATTRIBUTE</DefineConstants>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
   <PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
     <DefineConstants>$(DefineConstants);NO_ARRAY_EMPTY;NO_TASK_FROMEXCEPTION</DefineConstants>
     <DefineConstants>$(DefineConstants);NO_ARRAY_EMPTY;NO_TASK_FROMEXCEPTION</DefineConstants>

+ 3 - 2
Ix.NET/Source/Ix.Async.NET.sln

@@ -1,13 +1,14 @@
 
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26730.3
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28606.126
 MinimumVisualStudioVersion = 10.0.40219.1
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}"
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}"
 EndProject
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B733D97A-F1ED-4FC3-BF8E-9AC47A89DE96}"
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B733D97A-F1ED-4FC3-BF8E-9AC47A89DE96}"
 	ProjectSection(SolutionItems) = preProject
 	ProjectSection(SolutionItems) = preProject
 		..\..\.editorconfig = ..\..\.editorconfig
 		..\..\.editorconfig = ..\..\.editorconfig
+		AsyncQueryableGenerator.t4 = AsyncQueryableGenerator.t4
 		..\..\azure-pipelines.ix.yml = ..\..\azure-pipelines.ix.yml
 		..\..\azure-pipelines.ix.yml = ..\..\azure-pipelines.ix.yml
 		CodeCoverage.runsettings = CodeCoverage.runsettings
 		CodeCoverage.runsettings = CodeCoverage.runsettings
 		Directory.build.props = Directory.build.props
 		Directory.build.props = Directory.build.props

文件差異過大導致無法顯示
+ 342 - 240
Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs


+ 4 - 283
Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.tt

@@ -3,293 +3,14 @@
 // 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" #>
 <#@ assembly name="$(ProjectDir)\..\System.Interactive.Async\bin\$(Configuration)\net46\System.Interactive.Async.dll" #>
 <#@ assembly name="$(ProjectDir)\..\System.Interactive.Async\bin\$(Configuration)\net46\System.Interactive.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(AsyncEnumerableEx);
+var className = "AsyncQueryableEx";
 var nullableParameterNames = new[] { "comparer" };
 var nullableParameterNames = new[] { "comparer" };
-var exclude = new[] { "ForEach", "ForEachAsync", "ToEnumerable", "ToAsyncEnumerable", "ToObservable", "AsAsyncEnumerable" };
-
-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 AsyncQueryableEx
-    {
-<#
-// NOTE: Just including extension methods
-foreach (var m in typeof(AsyncEnumerableEx).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(() => AsyncQueryableEx." + 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
-        }
-
-<#
-}
+var exclude = new string[0];
 #>
 #>
-    }
-}
+<#@ include file="$(SolutionDir)\AsyncQueryableGenerator.t4" #>

+ 0 - 6
Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.cs

@@ -4,7 +4,6 @@
 
 
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq.Expressions;
 using System.Linq.Expressions;
-using System.Reflection;
 
 
 namespace System.Linq
 namespace System.Linq
 {
 {
@@ -23,10 +22,5 @@ namespace System.Linq
 
 
             return Expression.Constant(source, typeof(IAsyncEnumerable<TSource>));
             return Expression.Constant(source, typeof(IAsyncEnumerable<TSource>));
         }
         }
-
-        internal static MethodInfo InfoOf<R>(Expression<Func<R>> f)
-        {
-            return ((MethodCallExpression)f.Body).Method;
-        }
     }
     }
 }
 }

文件差異過大導致無法顯示
+ 349 - 245
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.Generated.cs


+ 3 - 282
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.Generated.tt

@@ -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" #>

+ 7 - 10
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.cs

@@ -35,6 +35,12 @@ namespace System.Linq
         }
         }
 
 
 #if HAS_VALUETUPLE
 #if HAS_VALUETUPLE
+        private static MethodInfo s_Zip__TFirst_TSecond__2__0;
+        
+        private static MethodInfo Zip__TFirst_TSecond__2__0(Type TFirst, Type TSecond) =>
+            (s_Zip__TFirst_TSecond__2__0 ??
+            (s_Zip__TFirst_TSecond__2__0 = new Func<IAsyncQueryable<object>, IAsyncEnumerable<object>, IAsyncQueryable<ValueTuple<object, object>>>(Zip<object, object>).GetMethodInfo().GetGenericMethodDefinition())).MakeGenericMethod(TFirst, TSecond);
+
         public static IAsyncQueryable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IAsyncQueryable<TFirst> first, IAsyncEnumerable<TSecond> second)
         public static IAsyncQueryable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IAsyncQueryable<TFirst> first, IAsyncEnumerable<TSecond> second)
         {
         {
             if (first == null)
             if (first == null)
@@ -42,11 +48,7 @@ namespace System.Linq
             if (second == null)
             if (second == null)
                 throw new ArgumentNullException(nameof(second));
                 throw new ArgumentNullException(nameof(second));
 
 
-#if CRIPPLED_REFLECTION
-            return first.Provider.CreateQuery<(TFirst, TSecond)>(Expression.Call(InfoOf(() => AsyncQueryable.Zip<TFirst, TSecond>(default(IAsyncQueryable<TFirst>), default(IAsyncEnumerable<TSecond>))), first.Expression, GetSourceExpression(second)));
-#else
-            return first.Provider.CreateQuery<(TFirst, TSecond)>(Expression.Call(((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TFirst), typeof(TSecond)), first.Expression, GetSourceExpression(second)));
-#endif
+            return first.Provider.CreateQuery<(TFirst, TSecond)>(Expression.Call(s_Zip__TFirst_TSecond__2__0(typeof(TFirst), typeof(TSecond)), first.Expression, GetSourceExpression(second)));
         }
         }
 #endif
 #endif
 
 
@@ -59,10 +61,5 @@ namespace System.Linq
 
 
             return Expression.Constant(source, typeof(IAsyncEnumerable<TSource>));
             return Expression.Constant(source, typeof(IAsyncEnumerable<TSource>));
         }
         }
-
-        internal static MethodInfo InfoOf<R>(Expression<Func<R>> f)
-        {
-            return ((MethodCallExpression)f.Body).Method;
-        }
     }
     }
 }
 }

部分文件因文件數量過多而無法顯示