diff --git a/README.md b/README.md index fa39b8e3..590fd0e3 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,6 @@ # System.Linq.Dynamic.Core This is a **.NET Core / Standard port** of the Microsoft assembly for the .Net 4.0 Dynamic language functionality. -[![Build status](https://ci.appveyor.com/api/projects/status/0c4v2bsvdqd57600?svg=true)](https://ci.appveyor.com/project/StefH/system-linq-dynamic-core) -[![codecov](https://codecov.io/gh/StefH/System.Linq.Dynamic.Core/branch/master/graph/badge.svg)](https://codecov.io/gh/StefH/System.Linq.Dynamic.Core) -[![Coverage Status](https://coveralls.io/repos/github/StefH/System.Linq.Dynamic.Core/badge.svg?branch=master)](https://coveralls.io/github/StefH/System.Linq.Dynamic.Core?branch=master) -[![GitHub issues](https://img.shields.io/github/issues/StefH/System.Linq.Dynamic.Core.svg)](https://github.com/StefH/System.Linq.Dynamic.Core/issues) -[![GitHub stars](https://img.shields.io/github/stars/StefH/System.Linq.Dynamic.Core.svg)](https://github.com/StefH/System.Linq.Dynamic.Core/stargazers) -[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/StefH/System.Linq.Dynamic.Core/master/LICENSE) - -| Project | NuGet | -| ------- | ----- | -| System.Linq.Dynamic.Core | [![NuGet Badge](https://buildstats.info/nuget/System.Linq.Dynamic.Core)](https://www.nuget.org/packages/System.Linq.Dynamic.Core) | -| EntityFramework.DynamicLinq | [![NuGet Badge](https://buildstats.info/nuget/EntityFramework.DynamicLinq)](https://www.nuget.org/packages/EntityFramework.DynamicLinq) | -| Microsoft.EntityFrameworkCore.DynamicLinq | [![NuGet Badge](https://buildstats.info/nuget/Microsoft.EntityFrameworkCore.DynamicLinq)](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.DynamicLinq) | - # Overview With this library it's possible to write Dynamic LINQ queries (string based) on an `IQueryable`: ```csharp @@ -25,11 +12,32 @@ var query = db.Customers # How to use There are several documentation resources: - - [Wiki][doc-wiki] : an overview from the basic functionality (correctness ~ 80%) - [API Documentation][doc-api] : a low-level API description website with some code samples - DynamicLinqWebDocs (TODO) +# Info +| | | +| --- | --- | +| ***Project*** |   | +|   **Chat** | [![Gitter](https://img.shields.io/gitter/room/system-linq-dynamic-core/Lobby.svg)](https://gitter.im/system-linq-dynamic-core/Lobby) | +|   **Issues** | [![GitHub issues](https://img.shields.io/github/issues/StefH/System.Linq.Dynamic.Core.svg)](https://github.com/StefH/System.Linq.Dynamic.Core/issues) | +| | | +| ***Quality*** |   | +|   **Build** | [![Build status](https://ci.appveyor.com/api/projects/status/0c4v2bsvdqd57600?svg=true)](https://ci.appveyor.com/project/StefH/system-linq-dynamic-core) | +|   **CodeFactor** | [![CodeFactor](https://www.codefactor.io/repository/github/stefh/system.linq.dynamic.core/badge)](https://www.codefactor.io/repository/github/stefh/system.linq.dynamic.core) +|   **Sonar Quality Gate** | [![Sonar Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=system.linq.dynamic.core&metric=alert_status)](https://sonarcloud.io/project/issues?id=system.linq.dynamic.core) | +|   **Sonar Bugs** | [![Sonar Bugs](https://sonarcloud.io/api/project_badges/measure?project=system.linq.dynamic.core&metric=bugs)](https://sonarcloud.io/project/issues?id=system.linq.dynamic.core&resolved=false&types=BUG) | +|   **Sonar Code Smells** | [![Sonar Code Smells](https://sonarcloud.io/api/project_badges/measure?project=system.linq.dynamic.core&metric=code_smells)](https://sonarcloud.io/project/issues?id=system.linq.dynamic.core&resolved=false&types=CODE_SMELL) | +|   **Sonar Coverage** | [![Sonar Coverage](https://sonarcloud.io/api/project_badges/measure?project=system.linq.dynamic.core&metric=coverage)](https://sonarcloud.io/component_measures?id=system.linq.dynamic.core&metric=coverage) | +|   **Codecov** | [![codecov](https://codecov.io/gh/StefH/System.Linq.Dynamic.Core/branch/master/graph/badge.svg)](https://codecov.io/gh/StefH/System.Linq.Dynamic.Core) | +|   **Coveralls** | [![Coverage Status](https://coveralls.io/repos/github/StefH/System.Linq.Dynamic.Core/badge.svg?branch=master)](https://coveralls.io/github/StefH/System.Linq.Dynamic.Core?branch=master) | +| | +| ***Nuget*** |   | +|   **System.Linq.Dynamic.Core** | [![NuGet Badge](https://buildstats.info/nuget/System.Linq.Dynamic.Core)](https://www.nuget.org/packages/System.Linq.Dynamic.Core) | +|   **EntityFramework.DynamicLinq** | [![NuGet Badge](https://buildstats.info/nuget/EntityFramework.DynamicLinq)](https://www.nuget.org/packages/EntityFramework.DynamicLinq) | +|   **Microsoft.EntityFrameworkCore.DynamicLinq** | [![NuGet Badge](https://buildstats.info/nuget/Microsoft.EntityFrameworkCore.DynamicLinq)](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.DynamicLinq) | + # Development Details diff --git a/appveyor.yml b/appveyor.yml index ce297b0a..b21afa23 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,20 +10,24 @@ platform: Any CPU init: - ps: $Env:LABEL = "CI" + $Env:APPVEYOR_BUILD_NUMBER.PadLeft(5, "0") +# install dotnet SDK and dotnet-sonarscanner install: - - ps: Start-FileDownload 'https://download.microsoft.com/download/D/7/2/D725E47F-A4F1-4285-8935-A91AE2FCC06A/dotnet-sdk-2.0.3-win-gs-x64.exe' - - cmd: dotnet-sdk-2.0.3-win-gs-x64.exe /quiet - - ps: $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = "true" +- ps: Start-FileDownload 'https://download.microsoft.com/download/4/0/9/40920432-3302-47a8-b13c-bbc4848ad114/dotnet-sdk-2.1.302-win-x64.exe' +- cmd: dotnet-sdk-2.1.302-win-x64.exe /quiet +- ps: $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = "true" +- dotnet tool install --global dotnet-sonarscanner environment: PATH: $(PATH);$(PROGRAMFILES)\dotnet\ COVERALLS_REPO_TOKEN: secure: tsTABRbCmdWFLT194XNIrpurerOfjN6cEoxt2RaSUfLmUIgra/+CwuqVkv0sPRop + SONAR_TOKEN: + secure: guog1+ttdnlD8sVgvizlewksm3qbO7dy2oZUcR8WhurWYvdOByinxXo732hmSaMT -build_script: +before_build: # Remove UAP10 and netstandard20 from csproj -- cmd: copy /Y src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.AppVeyor.csproj src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.csproj -- cmd: copy /Y src\Microsoft.EntityFrameworkCore.DynamicLinq\Microsoft.EntityFrameworkCore.DynamicLinq.AppVeyor.csproj src\Microsoft.EntityFrameworkCore.DynamicLinq\Microsoft.EntityFrameworkCore.DynamicLinq.csproj +#- cmd: copy /Y src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.AppVeyor.csproj src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.csproj +#- cmd: copy /Y src\Microsoft.EntityFrameworkCore.DynamicLinq\Microsoft.EntityFrameworkCore.DynamicLinq.AppVeyor.csproj src\Microsoft.EntityFrameworkCore.DynamicLinq\Microsoft.EntityFrameworkCore.DynamicLinq.csproj # Restore all - dotnet restore src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.csproj @@ -33,10 +37,13 @@ build_script: - dotnet restore test\System.Linq.Dynamic.Core.Tests\System.Linq.Dynamic.Core.Tests.csproj - dotnet restore test\EntityFramework.DynamicLinq.Tests\EntityFramework.DynamicLinq.Tests.csproj +build_script: +# Begin SonarScanner +- dotnet sonarscanner begin /k:"system.linq.dynamic.core" /d:sonar.organization="stefh-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="%SONAR_TOKEN%" /v:"%APPVEYOR_BUILD_NUMBER%" /d:sonar.cs.opencover.reportsPaths="%CD%\coverage.xml" + # Build Code -#- dotnet build src\EntityFramework.DynamicLinq\EntityFramework.DynamicLinq.csproj -c %CONFIGURATION% -#- dotnet build src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.csproj -c %CONFIGURATION% --framework netstandard1.3 -#- dotnet build src\Microsoft.EntityFrameworkCore.DynamicLinq\Microsoft.EntityFrameworkCore.DynamicLinq.csproj -c %CONFIGURATION% --framework netstandard1.3 +- dotnet build src\EntityFramework.DynamicLinq\EntityFramework.DynamicLinq.csproj -c %CONFIGURATION% +- dotnet build src\Microsoft.EntityFrameworkCore.DynamicLinq\Microsoft.EntityFrameworkCore.DynamicLinq.csproj -c %CONFIGURATION% --framework netstandard2.0 - dotnet build src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.csproj -c %CONFIGURATION% --framework netstandard2.0 # Build Tests @@ -44,15 +51,15 @@ build_script: - dotnet build test\EntityFramework.DynamicLinq.Tests\EntityFramework.DynamicLinq.Tests.csproj -c %CONFIGURATION% test_script: -# Run tests for EntityFramework.DynamicLinq -- dotnet test -c %CONFIGURATION% --no-build test\EntityFramework.DynamicLinq.Tests\EntityFramework.DynamicLinq.Tests.csproj - -after_test: # Use System.Linq.Dynamic.Core.Tests as coverage tests - - nuget.exe install OpenCover -ExcludeVersion - - nuget.exe install coveralls.net -ExcludeVersion -Version 0.7.0 - - pip install codecov +- nuget.exe install OpenCover -ExcludeVersion +- nuget.exe install coveralls.net -ExcludeVersion -Version 0.7.0 +- pip install codecov + +- cmd: '"OpenCover\tools\OpenCover.Console.exe" -target:dotnet.exe -targetargs:"test test\System.Linq.Dynamic.Core.Tests\System.Linq.Dynamic.Core.Tests.csproj --configuration %CONFIGURATION% --framework netcoreapp1.1 --no-build" -output:coverage.xml -register:user -filter:"+[Microsoft.EntityFrameworkCore.DynamicLinq]* +[System.Linq.Dynamic.Core]* -[*Tests*]*" -nodefaultfilters -returntargetcode -oldstyle' +- codecov -f "coverage.xml" +- coveralls.net\tools\csmacnz.Coveralls.exe --opencover -i .\coverage.xml +- dotnet sonarscanner end /d:sonar.login="%SONAR_TOKEN%" - - cmd: '"OpenCover\tools\OpenCover.Console.exe" -target:dotnet.exe -targetargs:"test test\System.Linq.Dynamic.Core.Tests\System.Linq.Dynamic.Core.Tests.csproj --configuration %CONFIGURATION% --framework netcoreapp1.1 --no-build" -output:coverage.xml -register:user -filter:"+[Microsoft.EntityFrameworkCore.DynamicLinq]* +[System.Linq.Dynamic.Core]* -[*Tests*]*" -nodefaultfilters -returntargetcode -oldstyle' - - codecov -f "coverage.xml" - - coveralls.net\tools\csmacnz.Coveralls.exe --opencover -i .\coverage.xml +# Run tests for EntityFramework.DynamicLinq +- dotnet test -c %CONFIGURATION% --no-build test\EntityFramework.DynamicLinq.Tests\EntityFramework.DynamicLinq.Tests.csproj diff --git a/codecov-local.cmd b/codecov-local.cmd index 63fe807c..fedc7213 100644 --- a/codecov-local.cmd +++ b/codecov-local.cmd @@ -1,9 +1,7 @@ rem https://www.appveyor.com/blog/2017/03/17/codecov/ -rem C:\Users\Stef\.nuget\packages\opencover\4.6.519\tools\OpenCover.Console.exe -target:"C:\Users\Stef\.nuget\packages\xunit.runner.console\2.3.0-beta1-build3642\tools\xunit.console.x86.exe" -targetargs:"test\System.Linq.Dynamic.Core.Tests\bin\Debug\netcoreapp1.1\System.Linq.Dynamic.Core.Tests.dll -noshadow" -output:".\coverage.xml" -filter:+[System.Linq.Dynamic.Core]*' - -%USERPROFILE%\.nuget\packages\opencover\4.6.519\tools\OpenCover.Console.exe -target:dotnet.exe -targetargs:"test test\System.Linq.Dynamic.Core.Tests\System.Linq.Dynamic.Core.Tests.csproj --no-build" -filter:"+[Microsoft.EntityFrameworkCore.DynamicLinq]* +[System.Linq.Dynamic.Core]* -[*Tests*]* -[System.Linq.Dynamic.Core]System.Linq.Dynamic.Core.Validation.*" -nodefaultfilters -output:coverage.xml -register:user -oldStyle +%USERPROFILE%\.nuget\packages\opencover\4.6.519\tools\OpenCover.Console.exe -target:dotnet.exe -targetargs:"test test\System.Linq.Dynamic.Core.Tests\System.Linq.Dynamic.Core.Tests.csproj --no-build --framework netcoreapp1.1" -filter:"+[EntityFramework.DynamicLinq]* +[Microsoft.EntityFrameworkCore.DynamicLinq]* +[System.Linq.Dynamic.Core]* -[*Tests*]* -[System.Linq.Dynamic.Core]System.Linq.Dynamic.Core.Validation.*" -nodefaultfilters -output:coverage.xml -register:user -oldStyle %USERPROFILE%\.nuget\packages\ReportGenerator\2.5.6\tools\ReportGenerator.exe -reports:"coverage.xml" -targetdir:"report" -start report\index.htm \ No newline at end of file +start report\index.htm diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_Check.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_Check.htm index 5dfc0c14..132bf797 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_Check.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_Check.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.Validation.Check Assembly:Microsoft.EntityFrameworkCore.DynamicLinq -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\Check.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\Check.cs Covered lines:11 Uncovered lines:60 Coverable lines:71 @@ -39,7 +39,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\Check.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\Check.cs

@@ -184,7 +184,7 @@

#LineLine coverage
 139}
- +

Methods/Properties

diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_CoreStrings.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_CoreStrings.htm index 2a79f84d..9458e6cf 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_CoreStrings.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_CoreStrings.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.Validation.CoreStrings Assembly:Microsoft.EntityFrameworkCore.DynamicLinq -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\CoreStrings.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\CoreStrings.cs Covered lines:0 Uncovered lines:12 Coverable lines:12 @@ -34,7 +34,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\CoreStrings.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Validation\CoreStrings.cs

@@ -51,7 +51,7 @@

- + @@ -59,7 +59,7 @@

- + @@ -67,7 +67,7 @@

- + @@ -75,13 +75,13 @@

- +
#LineLine coverage
 11        /// </summary>
 12        public static string ArgumentPropertyNull([CanBeNull] string property, [CanBeNull] string argument)
 013        {
 014            return string.Format(CultureInfo.CurrentCulture, $"The property '{property}' of the argument '{argument}' ca
 014            return string.Format(CultureInfo.CurrentCulture, "The property '{0}' of the argument '{1}' cannot be null.",
 015        }
 16
 17        /// <summary>
 19        /// </summary>
 20        public static string ArgumentIsEmpty([CanBeNull] string argumentName)
 021        {
 022            return string.Format(CultureInfo.CurrentCulture, $"The string argument '{argumentName}' cannot be empty.", a
 022            return string.Format(CultureInfo.CurrentCulture, "The string argument '{0}' cannot be empty.", argumentName)
 023        }
 24
 25        /// <summary>
 27        /// </summary>
 28        public static string InvalidEntityType([CanBeNull] Type type, [CanBeNull] string argumentName)
 029        {
 030            return string.Format(CultureInfo.CurrentCulture, $"The entity type '{type}' provided for the argument '{argu
 030            return string.Format(CultureInfo.CurrentCulture, "The entity type '{0}' provided for the argument '{1}' must
 031        }
 32
 33        /// <summary>
 35        /// </summary>
 36        public static string CollectionArgumentIsEmpty([CanBeNull] string argumentName)
 037        {
 038            return string.Format(CultureInfo.CurrentCulture, $"The collection argument '{argumentName}' must contain at 
 038            return string.Format(CultureInfo.CurrentCulture, "The collection argument '{0}' must contain at least one el
 039        }
 40    }
 41}
-
+

Methods/Properties

diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomIntrospectionExtensions.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomIntrospectionExtensions.htm index 5976ff0d..3ff6412e 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomIntrospectionExtensions.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomIntrospectionExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Reflection.CustomIntrospectionExtensions Assembly:Microsoft.EntityFrameworkCore.DynamicLinq -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs Covered lines:0 Uncovered lines:3 Coverable lines:3 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs

@@ -76,7 +76,7 @@

#LineLine coverage
 39}
-
+

Methods/Properties

diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomTypeBuilderExtensions.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomTypeBuilderExtensions.htm index c80e96d8..7522e7e6 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomTypeBuilderExtensions.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_CustomTypeBuilderExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Reflection.CustomTypeBuilderExtensions Assembly:Microsoft.EntityFrameworkCore.DynamicLinq -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs Covered lines:0 Uncovered lines:3 Coverable lines:3 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs

@@ -72,7 +72,7 @@

#LineLine coverage
 35}
-
+

Methods/Properties

diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_DynamicFunctions.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_DynamicFunctions.htm new file mode 100644 index 00000000..22f0ede4 --- /dev/null +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_DynamicFunctions.htm @@ -0,0 +1,30 @@ + + + + + +Microsoft.EntityFrameworkCore.DynamicLinq.DynamicFunctions - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + +
Class:Microsoft.EntityFrameworkCore.DynamicLinq.DynamicFunctions
Assembly:Microsoft.EntityFrameworkCore.DynamicLinq
File(s):
Covered lines:0
Uncovered lines:0
Coverable lines:0
Total lines:0
Line coverage:
+

File(s)

+

No files found. This usually happens if a file isn't covered by a test or the class does not contain any sequence points (e.g. a class that only contains auto properties).

+
+ + \ No newline at end of file diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_EntityFrameworkDynamicQueryableExtensions.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_EntityFrameworkDynamicQueryableExtensions.htm index 307a02bc..7be90852 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_EntityFrameworkDynamicQueryableExtensions.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_EntityFrameworkDynamicQueryableExtensions.htm @@ -15,11 +15,11 @@

Summary

Class:Microsoft.EntityFrameworkCore.DynamicLinq.EntityFrameworkDynamicQueryableExtensions Assembly:Microsoft.EntityFrameworkCore.DynamicLinq -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\Microsoft.EntityFrameworkCore.DynamicLinq\EFDynamicQueryableExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\Microsoft.EntityFrameworkCore.DynamicLinq\EFDynamicQueryableExtensions.cs Covered lines:96 Uncovered lines:42 Coverable lines:138 -Total lines:639 +Total lines:654 Line coverage:69.5% Branch coverage:50% @@ -55,7 +55,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\Microsoft.EntityFrameworkCore.DynamicLinq\EFDynamicQueryableExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\Microsoft.EntityFrameworkCore.DynamicLinq\EFDynamicQueryableExtensions.cs

@@ -65,125 +65,125 @@

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -216,519 +216,534 @@

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 4using System.Data.Entity.Infrastructure;
 5#endif
 6using System;
 7using System.Collections;
 8using System.Collections.Generic;
 9using System.Diagnostics;
 10using System.Linq;
 11using System.Linq.Dynamic.Core;
 12using System.Linq.Dynamic.Core.Extensions;
 13using System.Linq.Dynamic.Core.Validation;
 14using System.Linq.Expressions;
 15using System.Reflection;
 16using System.Threading;
 17using System.Threading.Tasks;
 18using JetBrains.Annotations;
 19
 20#if EFCORE
 21namespace Microsoft.EntityFrameworkCore.DynamicLinq
 22#else
 23namespace EntityFramework.DynamicLinq
 24#endif
 25{
 26    /// <summary>
 27    /// Provides a set of static Async methods for querying data structures that implement <see cref="IQueryable"/>.
 28    /// It allows dynamic string based querying. Very handy when, at compile time, you don't know the type of queries th
 29    /// or when downstream components only return column names to sort and filter by.
 30    /// </summary>
 31    public static class EntityFrameworkDynamicQueryableExtensions
 32    {
 133        private static readonly TraceSource _ts = new TraceSource(typeof(EntityFrameworkDynamicQueryableExtensions).Name
 34
 35        private static Expression OptimizeExpression(Expression expression)
 1436        {
 1437             if (ExtensibilityPoint.QueryOptimizer != null)
 1438            {
 1439                var optimized = ExtensibilityPoint.QueryOptimizer(expression);
 40
 41#if !(WINDOWS_APP45x || SILVERLIGHT)
 1442                 if (optimized != expression)
 043                {
 044                    _ts.TraceEvent(TraceEventType.Verbose, 0, "Expression before : {0}", expression);
 045                    _ts.TraceEvent(TraceEventType.Verbose, 0, "Expression after  : {0}", optimized);
 046                }
 47#endif
 1448                return optimized;
 49            }
 7using System.Diagnostics;
 8using System.Linq;
 9using System.Linq.Dynamic.Core;
 10using System.Linq.Dynamic.Core.Validation;
 11using System.Linq.Expressions;
 12using System.Reflection;
 13using System.Threading;
 14using System.Threading.Tasks;
 15using JetBrains.Annotations;
 16
 17#if EFCORE
 18namespace Microsoft.EntityFrameworkCore.DynamicLinq
 19#else
 20namespace EntityFramework.DynamicLinq
 21#endif
 22{
 23    /// <summary>
 24    /// Provides a set of static Async methods for querying data structures that implement <see cref="IQueryable"/>.
 25    /// It allows dynamic string based querying. Very handy when, at compile time, you don't know the type of queries th
 26    /// or when downstream components only return column names to sort and filter by.
 27    /// </summary>
 28    public static class EntityFrameworkDynamicQueryableExtensions
 29    {
 130        private static readonly TraceSource TraceSource = new TraceSource(typeof(EntityFrameworkDynamicQueryableExtensio
 31
 32        private static Expression OptimizeExpression(Expression expression)
 1433        {
 1434             if (ExtensibilityPoint.QueryOptimizer != null)
 1435            {
 1436                var optimized = ExtensibilityPoint.QueryOptimizer(expression);
 37
 38#if !(WINDOWS_APP45x || SILVERLIGHT)
 1439                 if (optimized != expression)
 040                {
 041                    TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Expression before : {0}", expression);
 042                    TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Expression after  : {0}", optimized);
 043                }
 44#endif
 1445                return optimized;
 46            }
 47
 048            return expression;
 1449        }
 50
 051            return expression;
 1452        }
 51        #region AnyAsync
 152        private static readonly MethodInfo _any = GetMethod(nameof(Queryable.Any));
 53
 54        #region AnyAsync
 155        private static readonly MethodInfo _any = GetMethod(nameof(Queryable.Any));
 56
 57        /// <summary>
 58        ///     Asynchronously determines whether a sequence contains any elements.
 59        /// </summary>
 60        /// <remarks>
 61        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 62        ///     that any asynchronous operations have completed before calling another method on this context.
 63        /// </remarks>
 64        /// <param name="source">
 65        ///     An <see cref="IQueryable" /> to check for being empty.
 54        /// <summary>
 55        ///     Asynchronously determines whether a sequence contains any elements.
 56        /// </summary>
 57        /// <remarks>
 58        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 59        ///     that any asynchronous operations have completed before calling another method on this context.
 60        /// </remarks>
 61        /// <param name="source">
 62        ///     An <see cref="IQueryable" /> to check for being empty.
 63        /// </param>
 64        /// <param name="cancellationToken">
 65        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 66        /// </param>
 67        /// <param name="cancellationToken">
 68        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 69        /// </param>
 70        /// <returns>
 71        ///     A task that represents the asynchronous operation.
 72        ///     The task result contains <c>true</c> if the source sequence contains any elements; otherwise, <c>false</
 73        /// </returns>
 74        public static Task<bool> AnyAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = defaul
 275        {
 276            Check.NotNull(source, nameof(source));
 277            Check.NotNull(cancellationToken, nameof(cancellationToken));
 78
 279            return ExecuteAsync<bool>(_any, source, cancellationToken);
 280        }
 67        /// <returns>
 68        ///     A task that represents the asynchronous operation.
 69        ///     The task result contains <c>true</c> if the source sequence contains any elements; otherwise, <c>false</
 70        /// </returns>
 71        [PublicAPI]
 72        public static Task<bool> AnyAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = defaul
 273        {
 274            Check.NotNull(source, nameof(source));
 275            Check.NotNull(cancellationToken, nameof(cancellationToken));
 76
 277            return ExecuteAsync<bool>(_any, source, cancellationToken);
 278        }
 79
 180        private static readonly MethodInfo _anyPredicate = GetMethod(nameof(Queryable.Any), 1);
 81
 182        private static readonly MethodInfo _anyPredicate = GetMethod(nameof(Queryable.Any), 1);
 83
 84        /// <summary>
 85        ///     Asynchronously determines whether any element of a sequence satisfies a condition.
 86        /// </summary>
 87        /// <remarks>
 88        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 89        ///     that any asynchronous operations have completed before calling another method on this context.
 90        /// </remarks>
 91        /// <param name="source">
 92        ///     An <see cref="IQueryable" /> whose elements to test for a condition.
 93        /// </param>
 94        /// <param name="predicate"> A function to test each element for a condition.</param>
 95        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 96        /// <returns>
 97        ///     A task that represents the asynchronous operation.
 98        ///     The task result contains <c>true</c> if any elements in the source sequence pass the test in the specifi
 99        ///     predicate; otherwise, <c>false</c>.
 100        /// </returns>
 101        public static Task<bool> AnyAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] para
 2102        {
 2103            return AnyAsync(source, predicate, default(CancellationToken), args);
 2104        }
 105
 106        /// <summary>
 107        ///     Asynchronously determines whether any element of a sequence satisfies a condition.
 108        /// </summary>
 109        /// <remarks>
 110        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 111        ///     that any asynchronous operations have completed before calling another method on this context.
 112        /// </remarks>
 113        /// <param name="source">
 114        ///     An <see cref="IQueryable" /> whose elements to test for a condition.
 115        /// </param>
 116        /// <param name="predicate"> A function to test each element for a condition.</param>
 117        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 118        /// <param name="cancellationToken">
 119        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 120        /// </param>
 121        /// <returns>
 122        ///     A task that represents the asynchronous operation.
 123        ///     The task result contains <c>true</c> if any elements in the source sequence pass the test in the specifi
 124        ///     predicate; otherwise, <c>false</c>.
 125        /// </returns>
 82        /// <summary>
 83        ///     Asynchronously determines whether any element of a sequence satisfies a condition.
 84        /// </summary>
 85        /// <remarks>
 86        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 87        ///     that any asynchronous operations have completed before calling another method on this context.
 88        /// </remarks>
 89        /// <param name="source">
 90        ///     An <see cref="IQueryable" /> whose elements to test for a condition.
 91        /// </param>
 92        /// <param name="predicate"> A function to test each element for a condition.</param>
 93        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 94        /// <returns>
 95        ///     A task that represents the asynchronous operation.
 96        ///     The task result contains <c>true</c> if any elements in the source sequence pass the test in the specifi
 97        ///     predicate; otherwise, <c>false</c>.
 98        /// </returns>
 99        [PublicAPI]
 100        public static Task<bool> AnyAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] para
 2101        {
 2102            return AnyAsync(source, predicate, default(CancellationToken), args);
 2103        }
 104
 105        /// <summary>
 106        ///     Asynchronously determines whether any element of a sequence satisfies a condition.
 107        /// </summary>
 108        /// <remarks>
 109        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 110        ///     that any asynchronous operations have completed before calling another method on this context.
 111        /// </remarks>
 112        /// <param name="source">
 113        ///     An <see cref="IQueryable" /> whose elements to test for a condition.
 114        /// </param>
 115        /// <param name="predicate"> A function to test each element for a condition.</param>
 116        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 117        /// <param name="cancellationToken">
 118        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 119        /// </param>
 120        /// <returns>
 121        ///     A task that represents the asynchronous operation.
 122        ///     The task result contains <c>true</c> if any elements in the source sequence pass the test in the specifi
 123        ///     predicate; otherwise, <c>false</c>.
 124        /// </returns>
 125        [PublicAPI]
 126        public static Task<bool> AnyAsync([NotNull] this IQueryable source, [NotNull] string predicate, CancellationToke
 2127        {
 2128            Check.NotNull(source, nameof(source));
 155        ///     A task that represents the asynchronous operation.
 156        ///     The task result contains the number of elements in the input sequence.
 157        /// </returns>
 158        public static Task<int> CountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = defau
 0159        {
 0160            Check.NotNull(source, nameof(source));
 0161            Check.NotNull(cancellationToken, nameof(cancellationToken));
 162
 0163            return ExecuteAsync<int>(_count, source, cancellationToken);
 0164        }
 165
 1166        private static readonly MethodInfo _countPredicate = GetMethod(nameof(Queryable.Count), 1);
 167
 168        /// <summary>
 169        ///     Asynchronously returns the number of elements in a sequence that satisfy a condition.
 170        /// </summary>
 171        /// <remarks>
 172        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 173        ///     that any asynchronous operations have completed before calling another method on this context.
 174        /// </remarks>
 175        /// <param name="source">
 176        ///     An <see cref="IQueryable" /> that contains the elements to be counted.
 177        /// </param>
 178        /// <param name="predicate"> A function to test each element for a condition. </param>
 179        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 180        /// <returns>
 181        ///     A task that represents the asynchronous operation.
 182        ///     The task result contains the number of elements in the sequence that satisfy the condition in the predic
 183        ///     function.
 184        /// </returns>
 185        public static Task<int> CountAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] par
 1186        {
 1187            return CountAsync(source, default(CancellationToken), predicate, args);
 1188        }
 189
 190        /// <summary>
 191        ///     Asynchronously returns the number of elements in a sequence that satisfy a condition.
 192        /// </summary>
 193        /// <remarks>
 194        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 195        ///     that any asynchronous operations have completed before calling another method on this context.
 196        /// </remarks>
 197        /// <param name="source">
 198        ///     An <see cref="IQueryable" /> that contains the elements to be counted.
 199        /// </param>
 200        /// <param name="predicate"> A function to test each element for a condition. </param>
 201        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 202        /// <param name="cancellationToken">
 203        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 204        /// </param>
 205        /// <returns>
 206        ///     A task that represents the asynchronous operation.
 207        ///     The task result contains the number of elements in the sequence that satisfy the condition in the predic
 208        ///     function.
 209        /// </returns>
 210        public static Task<int> CountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken, [NotNu
 1211        {
 1212            Check.NotNull(source, nameof(source));
 1213            Check.NotNull(predicate, nameof(predicate));
 1214            Check.NotNull(cancellationToken, nameof(cancellationToken));
 215
 1216            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 217
 1218            return ExecuteAsync<int>(_countPredicate, source, Expression.Quote(lambda), cancellationToken);
 1219        }
 220        #endregion Count
 221
 222        #region FirstAsync
 1223        private static readonly MethodInfo _first = GetMethod(nameof(Queryable.First));
 158        [PublicAPI]
 159        public static Task<int> CountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = defau
 0160        {
 0161            Check.NotNull(source, nameof(source));
 0162            Check.NotNull(cancellationToken, nameof(cancellationToken));
 163
 0164            return ExecuteAsync<int>(_count, source, cancellationToken);
 0165        }
 166
 1167        private static readonly MethodInfo _countPredicate = GetMethod(nameof(Queryable.Count), 1);
 168
 169        /// <summary>
 170        ///     Asynchronously returns the number of elements in a sequence that satisfy a condition.
 171        /// </summary>
 172        /// <remarks>
 173        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 174        ///     that any asynchronous operations have completed before calling another method on this context.
 175        /// </remarks>
 176        /// <param name="source">
 177        ///     An <see cref="IQueryable" /> that contains the elements to be counted.
 178        /// </param>
 179        /// <param name="predicate"> A function to test each element for a condition. </param>
 180        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 181        /// <returns>
 182        ///     A task that represents the asynchronous operation.
 183        ///     The task result contains the number of elements in the sequence that satisfy the condition in the predic
 184        ///     function.
 185        /// </returns>
 186        [PublicAPI]
 187        public static Task<int> CountAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] par
 1188        {
 1189            return CountAsync(source, default(CancellationToken), predicate, args);
 1190        }
 191
 192        /// <summary>
 193        ///     Asynchronously returns the number of elements in a sequence that satisfy a condition.
 194        /// </summary>
 195        /// <remarks>
 196        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 197        ///     that any asynchronous operations have completed before calling another method on this context.
 198        /// </remarks>
 199        /// <param name="source">
 200        ///     An <see cref="IQueryable" /> that contains the elements to be counted.
 201        /// </param>
 202        /// <param name="predicate"> A function to test each element for a condition. </param>
 203        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 204        /// <param name="cancellationToken">
 205        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 206        /// </param>
 207        /// <returns>
 208        ///     A task that represents the asynchronous operation.
 209        ///     The task result contains the number of elements in the sequence that satisfy the condition in the predic
 210        ///     function.
 211        /// </returns>
 212        [PublicAPI]
 213        public static Task<int> CountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken, [NotNu
 1214        {
 1215            Check.NotNull(source, nameof(source));
 1216            Check.NotNull(predicate, nameof(predicate));
 1217            Check.NotNull(cancellationToken, nameof(cancellationToken));
 218
 1219            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 220
 1221            return ExecuteAsync<int>(_countPredicate, source, Expression.Quote(lambda), cancellationToken);
 1222        }
 223        #endregion Count
 224
 225        /// <summary>
 226        ///     Asynchronously returns the first element of a sequence.
 227        /// </summary>
 228        /// <remarks>
 229        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 230        ///     that any asynchronous operations have completed before calling another method on this context.
 231        /// </remarks>
 232        /// <param name="source">
 233        ///     An <see cref="IQueryable" /> to return the first element of.
 234        /// </param>
 235        /// <param name="cancellationToken">
 236        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 225        #region FirstAsync
 1226        private static readonly MethodInfo _first = GetMethod(nameof(Queryable.First));
 227
 228        /// <summary>
 229        ///     Asynchronously returns the first element of a sequence.
 230        /// </summary>
 231        /// <remarks>
 232        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 233        ///     that any asynchronous operations have completed before calling another method on this context.
 234        /// </remarks>
 235        /// <param name="source">
 236        ///     An <see cref="IQueryable" /> to return the first element of.
 237        /// </param>
 238        /// <returns>
 239        ///     A task that represents the asynchronous operation.
 240        ///     The task result contains the first element in <paramref name="source" />.
 241        /// </returns>
 242        public static Task<dynamic> FirstAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = d
 2243        {
 2244            Check.NotNull(source, nameof(source));
 245
 2246            return ExecuteAsync<dynamic>(_first, source, cancellationToken);
 2247        }
 248
 1249        private static readonly MethodInfo _firstPredicate = GetMethod(nameof(Queryable.First), 1);
 250
 251        /// <summary>
 252        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition.
 253        /// </summary>
 254        /// <remarks>
 255        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 256        ///     that any asynchronous operations have completed before calling another method on this context.
 257        /// </remarks>
 258        /// <param name="source">
 259        ///     An <see cref="IQueryable" /> to return the first element of.
 260        /// </param>
 261        /// <param name="predicate"> A function to test each element for a condition. </param>
 262        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 263        /// <returns>
 264        ///     A task that represents the asynchronous operation.
 265        ///     The task result contains the first element in <paramref name="source" /> that passes the test in
 266        ///     <paramref name="predicate" />.
 267        /// </returns>
 268        public static Task<dynamic> FirstAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull]
 1269        {
 1270            return FirstAsync(source, default(CancellationToken), predicate, args);
 1271        }
 272
 273        /// <summary>
 274        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition.
 275        /// </summary>
 276        /// <remarks>
 277        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 278        ///     that any asynchronous operations have completed before calling another method on this context.
 279        /// </remarks>
 280        /// <param name="source">
 281        ///     An <see cref="IQueryable" /> to return the first element of.
 282        /// </param>
 283        /// <param name="predicate"> A function to test each element for a condition. </param>
 284        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 285        /// <param name="cancellationToken">
 286        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 238        /// <param name="cancellationToken">
 239        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 240        /// </param>
 241        /// <returns>
 242        ///     A task that represents the asynchronous operation.
 243        ///     The task result contains the first element in <paramref name="source" />.
 244        /// </returns>
 245        [PublicAPI]
 246        public static Task<dynamic> FirstAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = d
 2247        {
 2248            Check.NotNull(source, nameof(source));
 249
 2250            return ExecuteAsync<dynamic>(_first, source, cancellationToken);
 2251        }
 252
 1253        private static readonly MethodInfo _firstPredicate = GetMethod(nameof(Queryable.First), 1);
 254
 255        /// <summary>
 256        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition.
 257        /// </summary>
 258        /// <remarks>
 259        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 260        ///     that any asynchronous operations have completed before calling another method on this context.
 261        /// </remarks>
 262        /// <param name="source">
 263        ///     An <see cref="IQueryable" /> to return the first element of.
 264        /// </param>
 265        /// <param name="predicate"> A function to test each element for a condition. </param>
 266        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 267        /// <returns>
 268        ///     A task that represents the asynchronous operation.
 269        ///     The task result contains the first element in <paramref name="source" /> that passes the test in
 270        ///     <paramref name="predicate" />.
 271        /// </returns>
 272        [PublicAPI]
 273        public static Task<dynamic> FirstAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull]
 1274        {
 1275            return FirstAsync(source, default(CancellationToken), predicate, args);
 1276        }
 277
 278        /// <summary>
 279        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition.
 280        /// </summary>
 281        /// <remarks>
 282        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 283        ///     that any asynchronous operations have completed before calling another method on this context.
 284        /// </remarks>
 285        /// <param name="source">
 286        ///     An <see cref="IQueryable" /> to return the first element of.
 287        /// </param>
 288        /// <returns>
 289        ///     A task that represents the asynchronous operation.
 290        ///     The task result contains the first element in <paramref name="source" /> that passes the test in
 291        ///     <paramref name="predicate" />.
 292        /// </returns>
 293        public static Task<dynamic> FirstAsync([NotNull] this IQueryable source, CancellationToken cancellationToken, [N
 1294        {
 1295            Check.NotNull(source, nameof(source));
 1296            Check.NotNull(predicate, nameof(predicate));
 297
 1298            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 299
 1300            return ExecuteAsync<dynamic>(_firstPredicate, source, Expression.Quote(lambda), cancellationToken);
 1301        }
 302        #endregion FirstAsync
 288        /// <param name="predicate"> A function to test each element for a condition. </param>
 289        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 290        /// <param name="cancellationToken">
 291        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 292        /// </param>
 293        /// <returns>
 294        ///     A task that represents the asynchronous operation.
 295        ///     The task result contains the first element in <paramref name="source" /> that passes the test in
 296        ///     <paramref name="predicate" />.
 297        /// </returns>
 298        [PublicAPI]
 299        public static Task<dynamic> FirstAsync([NotNull] this IQueryable source, CancellationToken cancellationToken, [N
 1300        {
 1301            Check.NotNull(source, nameof(source));
 1302            Check.NotNull(predicate, nameof(predicate));
 303
 304        #region FirstOrDefaultAsync
 1305        private static readonly MethodInfo _firstOrDefault = GetMethod(nameof(Queryable.FirstOrDefault));
 306
 307        /// <summary>
 308        ///     Asynchronously returns the first element of a sequence, or a default value if the sequence contains no e
 309        /// </summary>
 310        /// <remarks>
 311        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 312        ///     that any asynchronous operations have completed before calling another method on this context.
 313        /// </remarks>
 314        /// <param name="source">
 315        ///     An <see cref="IQueryable" /> to return the first element of.
 316        /// </param>
 317        /// <param name="cancellationToken">
 318        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 319        /// </param>
 320        /// <returns>
 321        ///     A task that represents the asynchronous operation.
 322        ///     The task result contains <c>default</c> if
 323        ///     <paramref name="source" /> is empty; otherwise, the first element in <paramref name="source" />.
 324        /// </returns>
 325        public static Task<dynamic> FirstOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellation
 4326        {
 4327            Check.NotNull(source, nameof(source));
 4328            Check.NotNull(cancellationToken, nameof(cancellationToken));
 329
 4330            return ExecuteAsync<dynamic>(_firstOrDefault, source, cancellationToken);
 4331        }
 332
 1333        private static readonly MethodInfo _firstOrDefaultPredicate = GetMethod(nameof(Queryable.FirstOrDefault), 1);
 334
 335        /// <summary>
 336        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition
 337        ///     or a default value if no such element is found.
 338        /// </summary>
 339        /// <remarks>
 340        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 341        ///     that any asynchronous operations have completed before calling another method on this context.
 342        /// </remarks>
 343        /// <param name="source">
 344        ///     An <see cref="IQueryable" /> to return the first element of.
 345        /// </param>
 346        /// <param name="predicate"> A function to test each element for a condition. </param>
 347        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 348        /// <returns>
 349        ///     A task that represents the asynchronous operation.
 350        ///     The task result contains <c>default</c> if <paramref name="source" />
 351        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the fi
 352        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 353        /// </returns>
 354        public static Task<dynamic> FirstOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [C
 2355        {
 2356            return FirstOrDefaultAsync(source, default(CancellationToken), predicate, args);
 2357        }
 358
 359        /// <summary>
 360        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition
 361        ///     or a default value if no such element is found.
 362        /// </summary>
 363        /// <remarks>
 364        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 365        ///     that any asynchronous operations have completed before calling another method on this context.
 366        /// </remarks>
 367        /// <param name="source">
 368        ///     An <see cref="IQueryable" /> to return the first element of.
 369        /// </param>
 370        /// <param name="predicate"> A function to test each element for a condition. </param>
 371        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 372        /// <param name="cancellationToken">
 373        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 374        /// </param>
 375        /// <returns>
 376        ///     A task that represents the asynchronous operation.
 377        ///     The task result contains <c>default</c> if <paramref name="source" />
 378        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the fi
 379        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 380        /// </returns>
 381        public static Task<dynamic> FirstOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellation
 2382        {
 2383            Check.NotNull(source, nameof(source));
 2384            Check.NotNull(predicate, nameof(predicate));
 2385            Check.NotNull(cancellationToken, nameof(cancellationToken));
 386
 2387            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 388
 2389            return ExecuteAsync<dynamic>(_firstOrDefaultPredicate, source, Expression.Quote(lambda), cancellationToken);
 2390        }
 391        #endregion FirstOrDefault
 392
 393        #region LastAsync
 1394        private static readonly MethodInfo _last = GetMethod(nameof(Queryable.Last));
 1304            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 305
 1306            return ExecuteAsync<dynamic>(_firstPredicate, source, Expression.Quote(lambda), cancellationToken);
 1307        }
 308        #endregion FirstAsync
 309
 310        #region FirstOrDefaultAsync
 1311        private static readonly MethodInfo _firstOrDefault = GetMethod(nameof(Queryable.FirstOrDefault));
 312
 313        /// <summary>
 314        ///     Asynchronously returns the first element of a sequence, or a default value if the sequence contains no e
 315        /// </summary>
 316        /// <remarks>
 317        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 318        ///     that any asynchronous operations have completed before calling another method on this context.
 319        /// </remarks>
 320        /// <param name="source">
 321        ///     An <see cref="IQueryable" /> to return the first element of.
 322        /// </param>
 323        /// <param name="cancellationToken">
 324        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 325        /// </param>
 326        /// <returns>
 327        ///     A task that represents the asynchronous operation.
 328        ///     The task result contains <c>default</c> if
 329        ///     <paramref name="source" /> is empty; otherwise, the first element in <paramref name="source" />.
 330        /// </returns>
 331        [PublicAPI]
 332        public static Task<dynamic> FirstOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellation
 4333        {
 4334            Check.NotNull(source, nameof(source));
 4335            Check.NotNull(cancellationToken, nameof(cancellationToken));
 336
 4337            return ExecuteAsync<dynamic>(_firstOrDefault, source, cancellationToken);
 4338        }
 339
 1340        private static readonly MethodInfo _firstOrDefaultPredicate = GetMethod(nameof(Queryable.FirstOrDefault), 1);
 341
 342        /// <summary>
 343        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition
 344        ///     or a default value if no such element is found.
 345        /// </summary>
 346        /// <remarks>
 347        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 348        ///     that any asynchronous operations have completed before calling another method on this context.
 349        /// </remarks>
 350        /// <param name="source">
 351        ///     An <see cref="IQueryable" /> to return the first element of.
 352        /// </param>
 353        /// <param name="predicate"> A function to test each element for a condition. </param>
 354        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 355        /// <returns>
 356        ///     A task that represents the asynchronous operation.
 357        ///     The task result contains <c>default</c> if <paramref name="source" />
 358        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the fi
 359        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 360        /// </returns>
 361        [PublicAPI]
 362        public static Task<dynamic> FirstOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [C
 2363        {
 2364            return FirstOrDefaultAsync(source, default(CancellationToken), predicate, args);
 2365        }
 366
 367        /// <summary>
 368        ///     Asynchronously returns the first element of a sequence that satisfies a specified condition
 369        ///     or a default value if no such element is found.
 370        /// </summary>
 371        /// <remarks>
 372        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 373        ///     that any asynchronous operations have completed before calling another method on this context.
 374        /// </remarks>
 375        /// <param name="source">
 376        ///     An <see cref="IQueryable" /> to return the first element of.
 377        /// </param>
 378        /// <param name="predicate"> A function to test each element for a condition. </param>
 379        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 380        /// <param name="cancellationToken">
 381        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 382        /// </param>
 383        /// <returns>
 384        ///     A task that represents the asynchronous operation.
 385        ///     The task result contains <c>default</c> if <paramref name="source" />
 386        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the fi
 387        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 388        /// </returns>
 389        [PublicAPI]
 390        public static Task<dynamic> FirstOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellation
 2391        {
 2392            Check.NotNull(source, nameof(source));
 2393            Check.NotNull(predicate, nameof(predicate));
 2394            Check.NotNull(cancellationToken, nameof(cancellationToken));
 395
 396        /// <summary>
 397        ///     Asynchronously returns the last element of a sequence. [Maybe not supported : https://msdn.microsoft.com
 398        /// </summary>
 399        /// <remarks>
 400        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 401        ///     that any asynchronous operations have completed before calling another method on this context.
 402        /// </remarks>
 403        /// <param name="source">
 404        ///     An <see cref="IQueryable" /> to return the last element of.
 405        /// </param>
 406        /// <param name="cancellationToken">
 407        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 408        /// </param>
 409        /// <returns>
 410        ///     A task that represents the asynchronous operation.
 411        ///     The task result contains the last element in <paramref name="source" />.
 412        /// </returns>
 413        public static Task<dynamic> LastAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = de
 0414        {
 0415            Check.NotNull(source, nameof(source));
 416
 0417            return ExecuteAsync<dynamic>(_last, source, cancellationToken);
 0418        }
 419
 1420        private static readonly MethodInfo _lastPredicate = GetMethod(nameof(Queryable.Last), 1);
 421
 422        /// <summary>
 423        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition. [Maybe not s
 424        /// </summary>
 425        /// <remarks>
 426        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 427        ///     that any asynchronous operations have completed before calling another method on this context.
 428        /// </remarks>
 429        /// <param name="source">
 430        ///     An <see cref="IQueryable" /> to return the last element of.
 431        /// </param>
 432        /// <param name="predicate"> A function to test each element for a condition. </param>
 433        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 434        /// <returns>
 435        ///     A task that represents the asynchronous operation.
 436        ///     The task result contains the last element in <paramref name="source" /> that passes the test in
 437        ///     <paramref name="predicate" />.
 438        /// </returns>
 439        public static Task<dynamic> LastAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] 
 0440        {
 0441            return LastAsync(source, default(CancellationToken), predicate, args);
 0442        }
 443
 444        /// <summary>
 445        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition. [Maybe not s
 446        /// </summary>
 447        /// <remarks>
 448        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 449        ///     that any asynchronous operations have completed before calling another method on this context.
 450        /// </remarks>
 451        /// <param name="source">
 452        ///     An <see cref="IQueryable" /> to return the last element of.
 453        /// </param>
 454        /// <param name="predicate"> A function to test each element for a condition. </param>
 455        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 456        /// <param name="cancellationToken">
 457        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 458        /// </param>
 459        /// <returns>
 460        ///     A task that represents the asynchronous operation.
 461        ///     The task result contains the last element in <paramref name="source" /> that passes the test in
 462        ///     <paramref name="predicate" />.
 463        /// </returns>
 464        public static Task<dynamic> LastAsync([NotNull] this IQueryable source, CancellationToken cancellationToken, [No
 0465        {
 0466            Check.NotNull(source, nameof(source));
 0467            Check.NotNull(predicate, nameof(predicate));
 468
 0469            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 470
 0471            return ExecuteAsync<dynamic>(_lastPredicate, source, Expression.Quote(lambda), cancellationToken);
 0472        }
 473        #endregion LastAsync
 474
 475        #region LastOrDefaultAsync
 1476        private static readonly MethodInfo _lastOrDefault = GetMethod(nameof(Queryable.LastOrDefault));
 477
 478        /// <summary>
 479        ///     Asynchronously returns the last element of a sequence, or a default value if the sequence contains no el
 480        /// </summary>
 481        /// <remarks>
 482        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 483        ///     that any asynchronous operations have completed before calling another method on this context.
 484        /// </remarks>
 485        /// <param name="source">
 486        ///     An <see cref="IQueryable" /> to return the last element of.
 487        /// </param>
 488        /// <param name="cancellationToken">
 489        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 490        /// </param>
 491        /// <returns>
 492        ///     A task that represents the asynchronous operation.
 493        ///     The task result contains <c>default</c> if
 494        ///     <paramref name="source" /> is empty; otherwise, the last element in <paramref name="source" />.
 495        /// </returns>
 496        public static Task<dynamic> LastOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationT
 0497        {
 0498            Check.NotNull(source, nameof(source));
 0499            Check.NotNull(cancellationToken, nameof(cancellationToken));
 500
 0501            return ExecuteAsync<dynamic>(_lastOrDefault, source, cancellationToken);
 0502        }
 503
 1504        private static readonly MethodInfo _lastOrDefaultPredicate = GetMethod(nameof(Queryable.LastOrDefault), 1);
 505
 506        /// <summary>
 507        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition
 508        ///     or a default value if no such element is found. [Maybe not supported : https://msdn.microsoft.com/en-us/
 509        /// </summary>
 510        /// <remarks>
 511        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 512        ///     that any asynchronous operations have completed before calling another method on this context.
 513        /// </remarks>
 514        /// <param name="source">
 515        ///     An <see cref="IQueryable" /> to return the last element of.
 516        /// </param>
 517        /// <param name="predicate"> A function to test each element for a condition. </param>
 518        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 519        /// <returns>
 520        ///     A task that represents the asynchronous operation.
 521        ///     The task result contains <c>default</c> if <paramref name="source" />
 522        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the la
 523        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 524        /// </returns>
 525        public static Task<dynamic> LastOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [Ca
 0526        {
 0527            return LastOrDefaultAsync(source, default(CancellationToken), predicate, args);
 0528        }
 529
 530        /// <summary>
 531        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition
 532        ///     or a default value if no such element is found. [Maybe not supported : https://msdn.microsoft.com/en-us/
 533        /// </summary>
 534        /// <remarks>
 535        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 536        ///     that any asynchronous operations have completed before calling another method on this context.
 537        /// </remarks>
 538        /// <param name="source">
 539        ///     An <see cref="IQueryable" /> to return the last element of.
 540        /// </param>
 541        /// <param name="predicate"> A function to test each element for a condition. </param>
 542        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 543        /// <param name="cancellationToken">
 544        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 545        /// </param>
 546        /// <returns>
 547        ///     A task that represents the asynchronous operation.
 548        ///     The task result contains <c>default</c> if <paramref name="source" />
 549        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the la
 550        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 551        /// </returns>
 552        public static Task<dynamic> LastOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationT
 0553        {
 0554            Check.NotNull(source, nameof(source));
 0555            Check.NotNull(predicate, nameof(predicate));
 0556            Check.NotNull(cancellationToken, nameof(cancellationToken));
 557
 0558            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 559
 0560            return ExecuteAsync<dynamic>(_lastOrDefaultPredicate, source, Expression.Quote(lambda), cancellationToken);
 0561        }
 562        #endregion LastOrDefault
 563
 564        #region Private Helpers
 565        // Copied from https://github.com/aspnet/EntityFramework/blob/9186d0b78a3176587eeb0f557c331f635760fe92/src/Micro
 566        //private static Task<dynamic> ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, CancellationToken 
 567        //{
 568        //    var provider = source.Provider as IAsyncQueryProvider;
 569
 570        //    if (provider != null)
 571        //    {
 572        //        if (operatorMethodInfo.IsGenericMethod)
 573        //        {
 574        //            operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 575        //        }
 576
 577        //        return provider.ExecuteAsync<dynamic>(
 578        //            Expression.Call(null, operatorMethodInfo, source.Expression),
 579        //            cancellationToken);
 580        //    }
 581
 582        //    throw new InvalidOperationException(Res.IQueryableProviderNotAsync);
 583        //}
 2396            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 397
 2398            return ExecuteAsync<dynamic>(_firstOrDefaultPredicate, source, Expression.Quote(lambda), cancellationToken);
 2399        }
 400        #endregion FirstOrDefault
 401
 402        #region LastAsync
 1403        private static readonly MethodInfo _last = GetMethod(nameof(Queryable.Last));
 404
 405        /// <summary>
 406        ///     Asynchronously returns the last element of a sequence. [Maybe not supported : https://msdn.microsoft.com
 407        /// </summary>
 408        /// <remarks>
 409        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 410        ///     that any asynchronous operations have completed before calling another method on this context.
 411        /// </remarks>
 412        /// <param name="source">
 413        ///     An <see cref="IQueryable" /> to return the last element of.
 414        /// </param>
 415        /// <param name="cancellationToken">
 416        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 417        /// </param>
 418        /// <returns>
 419        ///     A task that represents the asynchronous operation.
 420        ///     The task result contains the last element in <paramref name="source" />.
 421        /// </returns>
 422        [PublicAPI]
 423        public static Task<dynamic> LastAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = de
 0424        {
 0425            Check.NotNull(source, nameof(source));
 426
 0427            return ExecuteAsync<dynamic>(_last, source, cancellationToken);
 0428        }
 429
 1430        private static readonly MethodInfo _lastPredicate = GetMethod(nameof(Queryable.Last), 1);
 431
 432        /// <summary>
 433        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition. [Maybe not s
 434        /// </summary>
 435        /// <remarks>
 436        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 437        ///     that any asynchronous operations have completed before calling another method on this context.
 438        /// </remarks>
 439        /// <param name="source">
 440        ///     An <see cref="IQueryable" /> to return the last element of.
 441        /// </param>
 442        /// <param name="predicate"> A function to test each element for a condition. </param>
 443        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 444        /// <returns>
 445        ///     A task that represents the asynchronous operation.
 446        ///     The task result contains the last element in <paramref name="source" /> that passes the test in
 447        ///     <paramref name="predicate" />.
 448        /// </returns>
 449        [PublicAPI]
 450        public static Task<dynamic> LastAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] 
 0451        {
 0452            return LastAsync(source, default(CancellationToken), predicate, args);
 0453        }
 454
 455        /// <summary>
 456        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition. [Maybe not s
 457        /// </summary>
 458        /// <remarks>
 459        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 460        ///     that any asynchronous operations have completed before calling another method on this context.
 461        /// </remarks>
 462        /// <param name="source">
 463        ///     An <see cref="IQueryable" /> to return the last element of.
 464        /// </param>
 465        /// <param name="predicate"> A function to test each element for a condition. </param>
 466        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 467        /// <param name="cancellationToken">
 468        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 469        /// </param>
 470        /// <returns>
 471        ///     A task that represents the asynchronous operation.
 472        ///     The task result contains the last element in <paramref name="source" /> that passes the test in
 473        ///     <paramref name="predicate" />.
 474        /// </returns>
 475        [PublicAPI]
 476        public static Task<dynamic> LastAsync([NotNull] this IQueryable source, CancellationToken cancellationToken, [No
 0477        {
 0478            Check.NotNull(source, nameof(source));
 0479            Check.NotNull(predicate, nameof(predicate));
 480
 0481            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 482
 0483            return ExecuteAsync<dynamic>(_lastPredicate, source, Expression.Quote(lambda), cancellationToken);
 0484        }
 485        #endregion LastAsync
 486
 487        #region LastOrDefaultAsync
 1488        private static readonly MethodInfo _lastOrDefault = GetMethod(nameof(Queryable.LastOrDefault));
 489
 490        /// <summary>
 491        ///     Asynchronously returns the last element of a sequence, or a default value if the sequence contains no el
 492        /// </summary>
 493        /// <remarks>
 494        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 495        ///     that any asynchronous operations have completed before calling another method on this context.
 496        /// </remarks>
 497        /// <param name="source">
 498        ///     An <see cref="IQueryable" /> to return the last element of.
 499        /// </param>
 500        /// <param name="cancellationToken">
 501        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 502        /// </param>
 503        /// <returns>
 504        ///     A task that represents the asynchronous operation.
 505        ///     The task result contains <c>default</c> if
 506        ///     <paramref name="source" /> is empty; otherwise, the last element in <paramref name="source" />.
 507        /// </returns>
 508        [PublicAPI]
 509        public static Task<dynamic> LastOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationT
 0510        {
 0511            Check.NotNull(source, nameof(source));
 0512            Check.NotNull(cancellationToken, nameof(cancellationToken));
 513
 0514            return ExecuteAsync<dynamic>(_lastOrDefault, source, cancellationToken);
 0515        }
 516
 1517        private static readonly MethodInfo _lastOrDefaultPredicate = GetMethod(nameof(Queryable.LastOrDefault), 1);
 518
 519        /// <summary>
 520        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition
 521        ///     or a default value if no such element is found. [Maybe not supported : https://msdn.microsoft.com/en-us/
 522        /// </summary>
 523        /// <remarks>
 524        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 525        ///     that any asynchronous operations have completed before calling another method on this context.
 526        /// </remarks>
 527        /// <param name="source">
 528        ///     An <see cref="IQueryable" /> to return the last element of.
 529        /// </param>
 530        /// <param name="predicate"> A function to test each element for a condition. </param>
 531        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 532        /// <returns>
 533        ///     A task that represents the asynchronous operation.
 534        ///     The task result contains <c>default</c> if <paramref name="source" />
 535        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the la
 536        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 537        /// </returns>
 538        [PublicAPI]
 539        public static Task<dynamic> LastOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [Ca
 0540        {
 0541            return LastOrDefaultAsync(source, default(CancellationToken), predicate, args);
 0542        }
 543
 544        /// <summary>
 545        ///     Asynchronously returns the last element of a sequence that satisfies a specified condition
 546        ///     or a default value if no such element is found. [Maybe not supported : https://msdn.microsoft.com/en-us/
 547        /// </summary>
 548        /// <remarks>
 549        ///     Multiple active operations on the same context instance are not supported.  Use 'await' to ensure
 550        ///     that any asynchronous operations have completed before calling another method on this context.
 551        /// </remarks>
 552        /// <param name="source">
 553        ///     An <see cref="IQueryable" /> to return the last element of.
 554        /// </param>
 555        /// <param name="predicate"> A function to test each element for a condition. </param>
 556        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 557        /// <param name="cancellationToken">
 558        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
 559        /// </param>
 560        /// <returns>
 561        ///     A task that represents the asynchronous operation.
 562        ///     The task result contains <c>default</c> if <paramref name="source" />
 563        ///     is empty or if no element passes the test specified by <paramref name="predicate" /> ; otherwise, the la
 564        ///     element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.
 565        /// </returns>
 566        [PublicAPI]
 567        public static Task<dynamic> LastOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationT
 0568        {
 0569            Check.NotNull(source, nameof(source));
 0570            Check.NotNull(predicate, nameof(predicate));
 0571            Check.NotNull(cancellationToken, nameof(cancellationToken));
 572
 0573            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(false, source.ElementType, null, predicate, ar
 574
 0575            return ExecuteAsync<dynamic>(_lastOrDefaultPredicate, source, Expression.Quote(lambda), cancellationToken);
 0576        }
 577        #endregion LastOrDefault
 578
 579        #region Private Helpers
 580        // Copied from https://github.com/aspnet/EntityFramework/blob/9186d0b78a3176587eeb0f557c331f635760fe92/src/Micro
 581        //private static Task<dynamic> ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, CancellationToken 
 582        //{
 583        //    var provider = source.Provider as IAsyncQueryProvider;
 584
 585        private static Task<TResult> ExecuteAsync<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Cancellatio
 8586        {
 587#if EFCORE
 8588            var provider = source.Provider as IAsyncQueryProvider;
 589#else
 590            var provider = source.Provider as IDbAsyncQueryProvider;
 591#endif
 592
 8593             if (provider != null)
 8594            {
 8595                 if (operatorMethodInfo.IsGenericMethod)
 8596                {
 8597                    operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 8598                }
 585        //    if (provider != null)
 586        //    {
 587        //        if (operatorMethodInfo.IsGenericMethod)
 588        //        {
 589        //            operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 590        //        }
 591
 592        //        return provider.ExecuteAsync<dynamic>(
 593        //            Expression.Call(null, operatorMethodInfo, source.Expression),
 594        //            cancellationToken);
 595        //    }
 596
 597        //    throw new InvalidOperationException(Res.IQueryableProviderNotAsync);
 598        //}
 599
 8600                var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 8601                return provider.ExecuteAsync<TResult>(optimized, cancellationToken);
 602            }
 603
 0604            throw new InvalidOperationException(Res.IQueryableProviderNotAsync);
 8605        }
 606
 607        private static Task<TResult> ExecuteAsync<TResult>(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpre
 0608            => ExecuteAsync<TResult>(operatorMethodInfo, source, Expression.Quote(expression), cancellationToken);
 609
 610        private static Task<TResult> ExecuteAsync<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Expression 
 6611        {
 612#if EFCORE
 6613            var provider = source.Provider as IAsyncQueryProvider;
 614#else
 615            var provider = source.Provider as IDbAsyncQueryProvider;
 616#endif
 617
 6618             if (provider != null)
 6619            {
 6620                operatorMethodInfo
 6621                    = operatorMethodInfo.GetGenericArguments().Length == 2
 6622                        ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(TResult))
 6623                        : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 600        private static Task<TResult> ExecuteAsync<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Cancellatio
 8601        {
 602#if EFCORE
 8603            var provider = source.Provider as IAsyncQueryProvider;
 604#else
 605            var provider = source.Provider as IDbAsyncQueryProvider;
 606#endif
 607
 8608             if (provider != null)
 8609            {
 8610                 if (operatorMethodInfo.IsGenericMethod)
 8611                {
 8612                    operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 8613                }
 614
 8615                var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 8616                return provider.ExecuteAsync<TResult>(optimized, cancellationToken);
 617            }
 618
 0619            throw new InvalidOperationException(Res.IQueryableProviderNotAsync);
 8620        }
 621
 622        private static Task<TResult> ExecuteAsync<TResult>(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpre
 0623            => ExecuteAsync<TResult>(operatorMethodInfo, source, Expression.Quote(expression), cancellationToken);
 624
 6625                var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, new[] { source.Expression, 
 6626                return provider.ExecuteAsync<TResult>(optimized, cancellationToken);
 627            }
 628
 0629            throw new InvalidOperationException(Res.IQueryableProviderNotAsync);
 6630        }
 631
 632        private static MethodInfo GetMethod<TResult>(string name, int parameterCount = 0, Func<MethodInfo, bool> predica
 0633            GetMethod(name, parameterCount, mi => (mi.ReturnType == typeof(TResult)) && ((predicate == null) || predicat
 634
 635        private static MethodInfo GetMethod(string name, int parameterCount = 0, Func<MethodInfo, bool> predicate = null
 36636            typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => (mi.GetParameters().Length == paramete
 637        #endregion Private Helpers
 638    }
 639}
 625        private static Task<TResult> ExecuteAsync<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Expression 
 6626        {
 627#if EFCORE
 6628            var provider = source.Provider as IAsyncQueryProvider;
 629#else
 630            var provider = source.Provider as IDbAsyncQueryProvider;
 631#endif
 632
 6633             if (provider != null)
 6634            {
 6635                operatorMethodInfo
 6636                    = operatorMethodInfo.GetGenericArguments().Length == 2
 6637                        ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(TResult))
 6638                        : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 639
 6640                var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, new[] { source.Expression, 
 6641                return provider.ExecuteAsync<TResult>(optimized, cancellationToken);
 642            }
 643
 0644            throw new InvalidOperationException(Res.IQueryableProviderNotAsync);
 6645        }
 646
 647        private static MethodInfo GetMethod<TResult>(string name, int parameterCount = 0, Func<MethodInfo, bool> predica
 0648            GetMethod(name, parameterCount, mi => (mi.ReturnType == typeof(TResult)) && ((predicate == null) || predicat
 649
 650        private static MethodInfo GetMethod(string name, int parameterCount = 0, Func<MethodInfo, bool> predicate = null
 36651            typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => (mi.GetParameters().Length == paramete
 652        #endregion Private Helpers
 653    }
 654}
-
+

Methods/Properties

-.cctor()
-OptimizeExpression(System.Linq.Expressions.Expression)
-AnyAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
-AnyAsync(System.Linq.IQueryable,System.String,System.Object[])
+.cctor()
+OptimizeExpression(System.Linq.Expressions.Expression)
+AnyAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
+AnyAsync(System.Linq.IQueryable,System.String,System.Object[])
AnyAsync(System.Linq.IQueryable,System.String,System.Threading.CancellationToken,System.Object[])
-CountAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
-CountAsync(System.Linq.IQueryable,System.String,System.Object[])
-CountAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
-FirstAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
-FirstAsync(System.Linq.IQueryable,System.String,System.Object[])
-FirstAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
-FirstOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
-FirstOrDefaultAsync(System.Linq.IQueryable,System.String,System.Object[])
-FirstOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
-LastAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
-LastAsync(System.Linq.IQueryable,System.String,System.Object[])
-LastAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
-LastOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
-LastOrDefaultAsync(System.Linq.IQueryable,System.String,System.Object[])
-LastOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
-ExecuteAsync(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Threading.CancellationToken)
-ExecuteAsync(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression,System.Threading.CancellationToken)
-ExecuteAsync(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression,System.Threading.CancellationToken)
-GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)
-GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)
+CountAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
+CountAsync(System.Linq.IQueryable,System.String,System.Object[])
+CountAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
+FirstAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
+FirstAsync(System.Linq.IQueryable,System.String,System.Object[])
+FirstAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
+FirstOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
+FirstOrDefaultAsync(System.Linq.IQueryable,System.String,System.Object[])
+FirstOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
+LastAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
+LastAsync(System.Linq.IQueryable,System.String,System.Object[])
+LastAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
+LastOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken)
+LastOrDefaultAsync(System.Linq.IQueryable,System.String,System.Object[])
+LastOrDefaultAsync(System.Linq.IQueryable,System.Threading.CancellationToken,System.String,System.Object[])
+ExecuteAsync(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Threading.CancellationToken)
+ExecuteAsync(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression,System.Threading.CancellationToken)
+ExecuteAsync(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression,System.Threading.CancellationToken)
+GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)
+GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)

diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_LinqProviderExtensions.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_LinqProviderExtensions.htm index 7e40024f..5788297a 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_LinqProviderExtensions.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_LinqProviderExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.Extensions.LinqProviderExtensions Assembly:Microsoft.EntityFrameworkCore.DynamicLinq -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs Covered lines:0 Uncovered lines:22 Coverable lines:22 @@ -33,7 +33,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs

@@ -90,7 +90,7 @@

#LineLine coverage
 51}
- +

Methods/Properties

diff --git a/report/Microsoft.EntityFrameworkCore.DynamicLinq_Res.htm b/report/Microsoft.EntityFrameworkCore.DynamicLinq_Res.htm index b78971d2..fcfff76d 100644 --- a/report/Microsoft.EntityFrameworkCore.DynamicLinq_Res.htm +++ b/report/Microsoft.EntityFrameworkCore.DynamicLinq_Res.htm @@ -25,6 +25,6 @@

Summary

File(s)

No files found. This usually happens if a file isn't covered by a test or the class does not contain any sequence points (e.g. a class that only contains auto properties).

-
+ \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_AbstractDynamicLinqCustomTypeProvider.htm b/report/System.Linq.Dynamic.Core_AbstractDynamicLinqCustomTypeProvider.htm index 294b8f2a..0030e02e 100644 --- a/report/System.Linq.Dynamic.Core_AbstractDynamicLinqCustomTypeProvider.htm +++ b/report/System.Linq.Dynamic.Core_AbstractDynamicLinqCustomTypeProvider.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.CustomTypeProviders.AbstractDynamicLinqCustomTypeProvider Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\AbstractDynamicLinqCustomTypeProvider.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\AbstractDynamicLinqCustomTypeProvider.cs Covered lines:23 Uncovered lines:2 Coverable lines:25 @@ -33,7 +33,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\AbstractDynamicLinqCustomTypeProvider.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\AbstractDynamicLinqCustomTypeProvider.cs

@@ -55,19 +55,19 @@

- - + + - + - + - + - + @@ -76,29 +76,29 @@

- - + + - - - + + + - - - + + + - - - - - - - - - + + + + + + + + + @@ -134,7 +134,7 @@

#LineLine coverage
 16        /// <param name="assemblies">The assemblies to process.</param>
 17        /// <returns>IEnumerable{Type}</returns>
 18        protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assembli
 1519        {
 1520            Check.NotNull(assemblies, nameof(assemblies));
 3619        {
 3620            Check.NotNull(assemblies, nameof(assemblies));
 21#if !NET35
 259522            assemblies = assemblies.Where(x => !x.IsDynamic);
 626722            assemblies = assemblies.Where(x => !x.IsDynamic);
 23#endif
 1524            var definedTypes = GetAssemblyTypes(assemblies);
 3624            var definedTypes = GetAssemblyTypes(assemblies);
 25
 26#if (WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 42570027            return definedTypes.Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(DynamicLinqTypeAttribut
 110040027            return definedTypes.Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(DynamicLinqTypeAttribut
 28#else
 29            return definedTypes.Where(x => x.GetCustomAttributes(typeof(DynamicLinqTypeAttribute), false).Any());
 30#endif
 1531        }
 3631        }
 32
 33#if (WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 34        /// <summary>
 37        /// <param name="assemblies">The assemblies to process.</param>
 38        /// <returns>IEnumerable{Type}</returns>
 39        protected IEnumerable<TypeInfo> GetAssemblyTypes([NotNull] IEnumerable<Assembly> assemblies)
 1540        {
 1541            Check.NotNull(assemblies, nameof(assemblies));
 3640        {
 3641            Check.NotNull(assemblies, nameof(assemblies));
 42
 520543            foreach (var assembly in assemblies)
 258044            {
 258045                IEnumerable<TypeInfo> definedTypes = null;
 1257043            foreach (var assembly in assemblies)
 623144            {
 623145                IEnumerable<TypeInfo> definedTypes = null;
 46
 47                try
 258048                {
 258049                    definedTypes = assembly.DefinedTypes;
 258050                }
 623148                {
 623149                    definedTypes = assembly.DefinedTypes;
 623150                }
 051                catch (Exception)
 052                { }
 53
 258054                 if (definedTypes != null)
 258055                {
 58305056                    foreach (var definedType in definedTypes)
 28765557                    {
 28765558                        yield return definedType;
 28765559                    }
 258060                }
 258061            }
 1562        }
 623154                 if (definedTypes != null)
 623155                {
 151521756                    foreach (var definedType in definedTypes)
 74826257                    {
 74826258                        yield return definedType;
 74826259                    }
 623160                }
 623161            }
 3662        }
 63#else
 64        /// <summary>
 65        /// Gets the assembly types in an Exception friendly way.
 95}
- +

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_AssemblyBuilderFactory.htm b/report/System.Linq.Dynamic.Core_AssemblyBuilderFactory.htm index 5e2a8223..111a6349 100644 --- a/report/System.Linq.Dynamic.Core_AssemblyBuilderFactory.htm +++ b/report/System.Linq.Dynamic.Core_AssemblyBuilderFactory.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.AssemblyBuilderFactory Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\AssemblyBuilderFactory.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\AssemblyBuilderFactory.cs Covered lines:3 Uncovered lines:0 Coverable lines:3 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\AssemblyBuilderFactory.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\AssemblyBuilderFactory.cs

@@ -62,7 +62,7 @@

#LineLine coverage
 25#endif
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_ConstantExpressionHelper.htm b/report/System.Linq.Dynamic.Core_ConstantExpressionHelper.htm new file mode 100644 index 00000000..3e9b7b3e --- /dev/null +++ b/report/System.Linq.Dynamic.Core_ConstantExpressionHelper.htm @@ -0,0 +1,82 @@ + + + + + +System.Linq.Dynamic.Core.Parser.ConstantExpressionHelper - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.ConstantExpressionHelper
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ConstantExpressionHelper.cs
Covered lines:14
Uncovered lines:0
Coverable lines:14
Total lines:29
Line coverage:100%
Branch coverage:100%
+

Metrics

+ + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
TryGetText(...)10100100
CreateLiteral(...)22100100
.cctor()10100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ConstantExpressionHelper.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Collections.Concurrent;
 2using System.Linq.Expressions;
 3
 4namespace System.Linq.Dynamic.Core.Parser
 5{
 6    internal static class ConstantExpressionHelper
 7    {
 18        private static readonly ConcurrentDictionary<object, Expression> Expressions = new ConcurrentDictionary<object, 
 19        private static readonly ConcurrentDictionary<Expression, string> Literals = new ConcurrentDictionary<Expression,
 10
 11        public static bool TryGetText(Expression expression, out string text)
 78712        {
 78713            return Literals.TryGetValue(expression, out text);
 78714        }
 15
 16        public static Expression CreateLiteral(object value, string text)
 25917        {
 25918             if (!Expressions.ContainsKey(value))
 7619            {
 7620                ConstantExpression constantExpression = Expression.Constant(value);
 21
 7622                Expressions.TryAdd(value, constantExpression);
 7623                Literals.TryAdd(constantExpression, text);
 7624            }
 25
 25926            return Expressions[value];
 25927        }
 28    }
 29}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_Constants.htm b/report/System.Linq.Dynamic.Core_Constants.htm new file mode 100644 index 00000000..ca9b1114 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_Constants.htm @@ -0,0 +1,59 @@ + + + + + +System.Linq.Dynamic.Core.Parser.Constants - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.Constants
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\Constants.cs
Covered lines:3
Uncovered lines:0
Coverable lines:3
Total lines:11
Line coverage:100%
+

Metrics

+ + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.cctor()10100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\Constants.cs

+ + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Linq.Expressions;
 2
 3namespace System.Linq.Dynamic.Core.Parser
 4{
 5    internal static class Constants
 6    {
 17        public static readonly Expression TrueLiteral = Expression.Constant(true);
 18        public static readonly Expression FalseLiteral = Expression.Constant(false);
 19        public static readonly Expression NullLiteral = Expression.Constant(null);
 10    }
 11}
+
+
+
+

Methods/Properties

+.cctor()
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_CustomIntrospectionExtensions.htm b/report/System.Linq.Dynamic.Core_CustomIntrospectionExtensions.htm index 675ed885..5388fc60 100644 --- a/report/System.Linq.Dynamic.Core_CustomIntrospectionExtensions.htm +++ b/report/System.Linq.Dynamic.Core_CustomIntrospectionExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Reflection.CustomIntrospectionExtensions Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs Covered lines:3 Uncovered lines:0 Coverable lines:3 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomIntrospectionExtensions.cs

@@ -68,15 +68,15 @@

- - - + + +
#LineLine coverage
 31        }
 32#else
 33        public static Type[] GetGenericTypeArguments(this TypeInfo typeInfo)
 327634        {
 327635            return typeInfo.GenericTypeArguments;
 327636        }
 382334        {
 382335            return typeInfo.GenericTypeArguments;
 382336        }
 37#endif
 38    }
 39}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_CustomTypeBuilderExtensions.htm b/report/System.Linq.Dynamic.Core_CustomTypeBuilderExtensions.htm index c27b8fe2..ed29ebe1 100644 --- a/report/System.Linq.Dynamic.Core_CustomTypeBuilderExtensions.htm +++ b/report/System.Linq.Dynamic.Core_CustomTypeBuilderExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Reflection.CustomTypeBuilderExtensions Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs Covered lines:3 Uncovered lines:0 Coverable lines:3 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Compatibility\CustomTypeBuilderExtensions.cs

@@ -44,9 +44,9 @@

- - - + + + @@ -72,7 +72,7 @@

#LineLine coverage
 7    {
 8#if !(NET35 || NET40 || SILVERLIGHT || WPSL || UAP10_0)
 9        public static Type CreateType(this TypeBuilder tb)
 3410        {
 3411            return tb.CreateTypeInfo().AsType();
 3412        }
 3010        {
 3011            return tb.CreateTypeInfo().AsType();
 3012        }
 13#endif
 14
 15#if NET35 || NET40 || SILVERLIGHT || WPSL
 35}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_DefaultAssemblyHelper.htm b/report/System.Linq.Dynamic.Core_DefaultAssemblyHelper.htm index 484aba91..64ee9e5d 100644 --- a/report/System.Linq.Dynamic.Core_DefaultAssemblyHelper.htm +++ b/report/System.Linq.Dynamic.Core_DefaultAssemblyHelper.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.DefaultAssemblyHelper Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DefaultAssemblyHelper.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DefaultAssemblyHelper.cs Covered lines:0 Uncovered lines:2 Coverable lines:2 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DefaultAssemblyHelper.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DefaultAssemblyHelper.cs

@@ -81,7 +81,7 @@

#LineLine coverage
 44}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_DefaultDynamicLinqCustomTypeProvider.htm b/report/System.Linq.Dynamic.Core_DefaultDynamicLinqCustomTypeProvider.htm index b062ef75..33fee4f5 100644 --- a/report/System.Linq.Dynamic.Core_DefaultDynamicLinqCustomTypeProvider.htm +++ b/report/System.Linq.Dynamic.Core_DefaultDynamicLinqCustomTypeProvider.htm @@ -15,11 +15,11 @@

Summary

Class:System.Linq.Dynamic.Core.CustomTypeProviders.DefaultDynamicLinqCustomTypeProvider Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\DefaultDynamicLinqCustomTypeProvider.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\DefaultDynamicLinqCustomTypeProvider.cs Covered lines:0 -Uncovered lines:8 -Coverable lines:8 -Total lines:32 +Uncovered lines:9 +Coverable lines:9 +Total lines:34 Line coverage:0% Branch coverage:0% @@ -33,7 +33,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\DefaultDynamicLinqCustomTypeProvider.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\CustomTypeProviders\DefaultDynamicLinqCustomTypeProvider.cs

@@ -60,18 +60,20 @@

- - - - - - - - - + + + + + + + + + + +
#LineLine coverage
 21        public virtual HashSet<Type> GetCustomTypes()
 022        {
 023             if (_customTypes != null)
 024                return _customTypes;
 25
 026            IEnumerable<Assembly> assemblies = _assemblyHelper.GetAssemblies();
 027            _customTypes = new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
 028            return _customTypes;
 029        }
 30    }
 31}
 32#endif
 024            {
 025                return _customTypes;
 26            }
 27
 028            IEnumerable<Assembly> assemblies = _assemblyHelper.GetAssemblies();
 029            _customTypes = new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
 030            return _customTypes;
 031        }
 32    }
 33}
 34#endif
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_DynamicClass.htm b/report/System.Linq.Dynamic.Core_DynamicClass.htm index 49fad724..8b1d48bb 100644 --- a/report/System.Linq.Dynamic.Core_DynamicClass.htm +++ b/report/System.Linq.Dynamic.Core_DynamicClass.htm @@ -15,12 +15,12 @@

Summary

Class:System.Linq.Dynamic.Core.DynamicClass Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClass.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClass.cs Covered lines:5 -Uncovered lines:51 -Coverable lines:56 -Total lines:328 -Line coverage:8.9% +Uncovered lines:60 +Coverable lines:65 +Total lines:178 +Line coverage:7.6% Branch coverage:0% @@ -38,354 +38,204 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClass.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClass.cs

- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Collections;
 1#if !UAP10_0 && !NET35
 2using System.Collections.Generic;
 3using System.Reflection;
 4
 5#if UAP10_0
 6using System.Dynamic;
 7
 8namespace System.Linq.Dynamic.Core
 9{
 10    /// <summary>
 11    /// Provides a base class for dynamic objects for UAP10_0.
 12    /// </summary>
 13    public class DynamicClass : DynamicObject
 14    {
 15        readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
 16
 17        /// <summary>
 18        /// Initializes a new instance of the <see cref="DynamicClass"/> class.
 19        /// </summary>
 20        /// <param name="propertylist">The propertylist.</param>
 21        public DynamicClass(params KeyValuePair<string, object>[] propertylist)
 22        {
 23            foreach (var kvp in propertylist)
 24            {
 25                _properties.Add(kvp.Key, kvp.Value);
 26            }
 27        }
 28
 29        /// <summary>
 30        /// Gets or sets the <see cref="object"/> with the specified name.
 31        /// </summary>
 32        /// <value>
 33        /// The <see cref="object"/>.
 34        /// </value>
 35        /// <param name="name">The name.</param>
 36        /// <returns>Value from the property.</returns>
 37        public object this[string name]
 38        {
 39            get
 40            {
 41                object result;
 42                if (_properties.TryGetValue(name, out result))
 43                    return result;
 44
 45                return null;
 46            }
 47            set
 48            {
 49                if (_properties.ContainsKey(name))
 50                    _properties[name] = value;
 51                else
 52                    _properties.Add(name, value);
 53            }
 54        }
 55
 56        /// <summary>
 57        /// Returns the enumeration of all dynamic member names.
 58        /// </summary>
 59        /// <returns>
 60        /// A sequence that contains dynamic member names.
 61        /// </returns>
 62        public override IEnumerable<string> GetDynamicMemberNames()
 63        {
 64            return _properties.Keys;
 65        }
 66
 67        /// <summary>
 68        /// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:Sys
 69        /// </summary>
 70        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Nam
 71        /// <param name="result">The result of the get operation. For example, if the method is called for a property, y
 72        /// <returns>
 73        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of 
 74        /// </returns>
 75        public override bool TryGetMember(GetMemberBinder binder, out object result)
 76        {
 77            var name = binder.Name;
 78            _properties.TryGetValue(name, out result);
 79
 80            return true;
 81        }
 3using System.Dynamic;
 4using System.Reflection;
 5
 6namespace System.Linq.Dynamic.Core
 7{
 8    /// <summary>
 9    /// Provides a base class for dynamic objects.
 10    ///
 11    /// In addition to the methods defined here, the following items are added using reflection:
 12    /// - default constructor
 13    /// - constructor with all the properties as parameters (if not linq-to-entities)
 14    /// - all properties (also with getter and setters)
 15    /// - ToString() method
 16    /// - Equals() method
 17    /// - GetHashCode() method
 18    /// </summary>
 19    public abstract class DynamicClass : DynamicObject
 20    {
 21        private Dictionary<string, object> _propertiesDictionary;
 22
 23        private Dictionary<string, object> Properties
 24        {
 25            get
 026            {
 027                 if (_propertiesDictionary == null)
 028                {
 029                    _propertiesDictionary = new Dictionary<string, object>();
 30
 031                    foreach (PropertyInfo pi in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
 032                    {
 033                        int parameters = pi.GetIndexParameters().Length;
 034                         if (parameters > 0)
 035                        {
 36                            // The property is an indexer, skip this.
 037                            continue;
 38                        }
 39
 040                        _propertiesDictionary.Add(pi.Name, pi.GetValue(this, null));
 041                    }
 042                }
 43
 044                return _propertiesDictionary;
 045            }
 46        }
 47
 48        /// <summary>
 49        /// Gets the dynamic property by name.
 50        /// </summary>
 51        /// <typeparam name="T">The type.</typeparam>
 52        /// <param name="propertyName">Name of the property.</param>
 53        /// <returns>T</returns>
 54        public T GetDynamicPropertyValue<T>(string propertyName)
 5455        {
 5456            var type = GetType();
 5457            var propInfo = type.GetProperty(propertyName);
 58
 5459            return (T)propInfo.GetValue(this, null);
 5460        }
 61
 62        /// <summary>
 63        /// Gets the dynamic property value by name.
 64        /// </summary>
 65        /// <param name="propertyName">Name of the property.</param>
 66        /// <returns>value</returns>
 67        public object GetDynamicPropertyValue(string propertyName)
 068        {
 069            return GetDynamicPropertyValue<object>(propertyName);
 070        }
 71
 72        /// <summary>
 73        /// Sets the dynamic property value by name.
 74        /// </summary>
 75        /// <typeparam name="T">The type.</typeparam>
 76        /// <param name="propertyName">Name of the property.</param>
 77        /// <param name="value">The value.</param>
 78        public void SetDynamicPropertyValue<T>(string propertyName, T value)
 079        {
 080            var type = GetType();
 081            var propInfo = type.GetProperty(propertyName);
 82
 83        /// <summary>
 84        /// Provides the implementation for operations that set member values. Classes derived from the <see cref="T:Sys
 85        /// </summary>
 86        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Nam
 87        /// <param name="value">The value to set to the member. For example, for sampleObject.SampleProperty = "Test", w
 88        /// <returns>
 89        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of 
 90        /// </returns>
 91        public override bool TrySetMember(SetMemberBinder binder, object value)
 92        {
 93            var name = binder.Name;
 94            if (_properties.ContainsKey(name))
 95                _properties[name] = value;
 96            else
 97                _properties.Add(name, value);
 98
 99            return true;
 100        }
 101    }
 102}
 103# elif NET35
 104namespace System.Linq.Dynamic.Core
 105{
 106    /// <summary>
 107    /// Provides a base class for dynamic objects for Net 3.5
 108    /// </summary>
 109    public abstract class DynamicClass
 110    {
 111        /// <summary>
 112        /// Gets the dynamic property by name.
 113        /// </summary>
 114        /// <typeparam name="T">The type.</typeparam>
 115        /// <param name="propertyName">Name of the property.</param>
 116        /// <returns>T</returns>
 117        public T GetDynamicPropertyValue<T>(string propertyName)
 118        {
 119            var type = GetType();
 120            var propInfo = type.GetProperty(propertyName);
 121
 122            return (T)propInfo.GetValue(this, null);
 123        }
 124
 125        /// <summary>
 126        /// Gets the dynamic property value by name.
 127        /// </summary>
 128        /// <param name="propertyName">Name of the property.</param>
 129        /// <returns>value</returns>
 130        public object GetDynamicPropertyValue(string propertyName)
 131        {
 132            return GetDynamicPropertyValue<object>(propertyName);
 133        }
 134
 135        /// <summary>
 136        /// Sets the dynamic property value by name.
 137        /// </summary>
 138        /// <typeparam name="T">The type.</typeparam>
 139        /// <param name="propertyName">Name of the property.</param>
 140        /// <param name="value">The value.</param>
 141        public void SetDynamicPropertyValue<T>(string propertyName, T value)
 142        {
 143            var type = GetType();
 144            var propInfo = type.GetProperty(propertyName);
 145
 146            propInfo.SetValue(this, value, null);
 147        }
 148
 149        /// <summary>
 150        /// Sets the dynamic property value by name.
 151        /// </summary>
 152        /// <param name="propertyName">Name of the property.</param>
 153        /// <param name="value">The value.</param>
 154        public void SetDynamicPropertyValue(string propertyName, object value)
 155        {
 156            SetDynamicPropertyValue<object>(propertyName, value);
 157        }
 158    }
 159}
 160#else
 161using System.Dynamic;
 162
 163namespace System.Linq.Dynamic.Core
 164{
 165    /// <summary>
 166    /// Provides a base class for dynamic objects.
 167    ///
 168    /// In addition to the methods defined here, the following items are added using reflection:
 169    /// - default constructor
 170    /// - constructor with all the properties as parameters (if not linq-to-entities)
 171    /// - all properties (also with getter and setters)
 172    /// - ToString() method
 173    /// - Equals() method
 174    /// - GetHashCode() method
 175    /// </summary>
 176    public abstract class DynamicClass : DynamicObject
 177    {
 178        private Dictionary<string, object> _propertiesDictionary;
 179
 180        private Dictionary<string, object> _properties
 181        {
 182            get
 0183            {
 0184                 if (_propertiesDictionary == null)
 0185                {
 0186                    _propertiesDictionary = new Dictionary<string, object>();
 187
 0188                    foreach (PropertyInfo pi in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
 0189                    {
 0190                        int parameters = pi.GetIndexParameters().Length;
 0191                         if (parameters > 0)
 0192                        {
 193                            // The property is an indexer, skip this.
 0194                            continue;
 195                        }
 196
 0197                        _propertiesDictionary.Add(pi.Name, pi.GetValue(this, null));
 0198                    }
 0199                }
 200
 0201                return _propertiesDictionary;
 0202            }
 203        }
 204
 205        /// <summary>
 206        /// Gets the dynamic property by name.
 207        /// </summary>
 208        /// <typeparam name="T">The type.</typeparam>
 209        /// <param name="propertyName">Name of the property.</param>
 210        /// <returns>T</returns>
 211        public T GetDynamicPropertyValue<T>(string propertyName)
 16212        {
 16213            var type = GetType();
 16214            var propInfo = type.GetProperty(propertyName);
 215
 16216            return (T)propInfo.GetValue(this, null);
 16217        }
 218
 219        /// <summary>
 220        /// Gets the dynamic property value by name.
 221        /// </summary>
 222        /// <param name="propertyName">Name of the property.</param>
 223        /// <returns>value</returns>
 224        public object GetDynamicPropertyValue(string propertyName)
 0225        {
 0226            return GetDynamicPropertyValue<object>(propertyName);
 0227        }
 228
 229        /// <summary>
 230        /// Sets the dynamic property value by name.
 231        /// </summary>
 232        /// <typeparam name="T">The type.</typeparam>
 233        /// <param name="propertyName">Name of the property.</param>
 234        /// <param name="value">The value.</param>
 235        public void SetDynamicPropertyValue<T>(string propertyName, T value)
 0236        {
 0237            var type = GetType();
 0238            var propInfo = type.GetProperty(propertyName);
 239
 0240            propInfo.SetValue(this, value, null);
 0241        }
 242
 243        /// <summary>
 244        /// Sets the dynamic property value by name.
 245        /// </summary>
 246        /// <param name="propertyName">Name of the property.</param>
 247        /// <param name="value">The value.</param>
 248        public void SetDynamicPropertyValue(string propertyName, object value)
 0249        {
 0250            SetDynamicPropertyValue<object>(propertyName, value);
 0251        }
 252
 253        /// <summary>
 254        /// Gets or sets the <see cref="object"/> with the specified name.
 255        /// </summary>
 256        /// <value>
 257        /// The <see cref="object"/>.
 258        /// </value>
 259        /// <param name="name">The name.</param>
 260        /// <returns>Value from the property.</returns>
 261        public object this[string name]
 262        {
 263            get
 0264            {
 265                object result;
 0266                 if (_properties.TryGetValue(name, out result))
 0267                    return result;
 268
 0269                return null;
 0270            }
 271
 272            set
 0273            {
 0274                 if (_properties.ContainsKey(name))
 0275                    _properties[name] = value;
 276                else
 0277                    _properties.Add(name, value);
 0278            }
 279        }
 280
 281        /// <summary>
 282        /// Returns the enumeration of all dynamic member names.
 283        /// </summary>
 284        /// <returns>
 285        /// A sequence that contains dynamic member names.
 286        /// </returns>
 287        public override IEnumerable<string> GetDynamicMemberNames()
 0288        {
 0289            return _properties.Keys;
 0290        }
 291
 292        /// <summary>
 293        /// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:Sys
 294        /// </summary>
 295        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Nam
 296        /// <param name="result">The result of the get operation. For example, if the method is called for a property, y
 297        /// <returns>
 298        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of 
 299        /// </returns>
 300        public override bool TryGetMember(GetMemberBinder binder, out object result)
 0301        {
 0302            string name = binder.Name;
 0303            _properties.TryGetValue(name, out result);
 304
 0305            return true;
 0306        }
 307
 308        /// <summary>
 309        /// Provides the implementation for operations that set member values. Classes derived from the <see cref="T:Sys
 310        /// </summary>
 311        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Nam
 312        /// <param name="value">The value to set to the member. For example, for sampleObject.SampleProperty = "Test", w
 313        /// <returns>
 314        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of 
 315        /// </returns>
 316        public override bool TrySetMember(SetMemberBinder binder, object value)
 0317        {
 0318            string name = binder.Name;
 0319             if (_properties.ContainsKey(name))
 0320                _properties[name] = value;
 321            else
 0322                _properties.Add(name, value);
 323
 0324            return true;
 0325        }
 326    }
 327}
 328#endif
 083            propInfo.SetValue(this, value, null);
 084        }
 85
 86        /// <summary>
 87        /// Sets the dynamic property value by name.
 88        /// </summary>
 89        /// <param name="propertyName">Name of the property.</param>
 90        /// <param name="value">The value.</param>
 91        public void SetDynamicPropertyValue(string propertyName, object value)
 092        {
 093            SetDynamicPropertyValue<object>(propertyName, value);
 094        }
 95
 96        /// <summary>
 97        /// Gets or sets the <see cref="object"/> with the specified name.
 98        /// </summary>
 99        /// <value>The <see cref="object"/>.</value>
 100        /// <param name="name">The name.</param>
 101        /// <returns>Value from the property.</returns>
 102        public object this[string name]
 103        {
 104            get
 0105            {
 0106                 if (Properties.TryGetValue(name, out object result))
 0107                {
 0108                    return result;
 109                }
 110
 0111                return null;
 0112            }
 113
 114            set
 0115            {
 0116                 if (Properties.ContainsKey(name))
 0117                {
 0118                    Properties[name] = value;
 0119                }
 120                else
 0121                {
 0122                    Properties.Add(name, value);
 0123                }
 0124            }
 125        }
 126
 127        /// <summary>
 128        /// Returns the enumeration of all dynamic member names.
 129        /// </summary>
 130        /// <returns>
 131        /// A sequence that contains dynamic member names.
 132        /// </returns>
 133        public override IEnumerable<string> GetDynamicMemberNames()
 0134        {
 0135            return Properties.Keys;
 0136        }
 137
 138        /// <summary>
 139        /// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:Sys
 140        /// </summary>
 141        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Nam
 142        /// <param name="result">The result of the get operation. For example, if the method is called for a property, y
 143        /// <returns>
 144        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of 
 145        /// </returns>
 146        public override bool TryGetMember(GetMemberBinder binder, out object result)
 0147        {
 0148            string name = binder.Name;
 0149            Properties.TryGetValue(name, out result);
 150
 0151            return true;
 0152        }
 153
 154        /// <summary>
 155        /// Provides the implementation for operations that set member values. Classes derived from the <see cref="T:Sys
 156        /// </summary>
 157        /// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Nam
 158        /// <param name="value">The value to set to the member. For example, for sampleObject.SampleProperty = "Test", w
 159        /// <returns>
 160        /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of 
 161        /// </returns>
 162        public override bool TrySetMember(SetMemberBinder binder, object value)
 0163        {
 0164            string name = binder.Name;
 0165             if (Properties.ContainsKey(name))
 0166            {
 0167                Properties[name] = value;
 0168            }
 169            else
 0170            {
 0171                Properties.Add(name, value);
 0172            }
 173
 0174            return true;
 0175        }
 176    }
 177}
 178#endif
-
+

Methods/Properties

-_properties()
-GetDynamicPropertyValue(System.String)
-GetDynamicPropertyValue(System.String)
-SetDynamicPropertyValue(System.String,T)
-SetDynamicPropertyValue(System.String,System.Object)
-Item(System.String)
-Item(System.String,System.Object)
-GetDynamicMemberNames()
-TryGetMember(System.Dynamic.GetMemberBinder,System.Object&)
-TrySetMember(System.Dynamic.SetMemberBinder,System.Object)
+Properties()
+GetDynamicPropertyValue(System.String)
+GetDynamicPropertyValue(System.String)
+SetDynamicPropertyValue(System.String,T)
+SetDynamicPropertyValue(System.String,System.Object)
+Item(System.String)
+Item(System.String,System.Object)
+GetDynamicMemberNames()
+TryGetMember(System.Dynamic.GetMemberBinder,System.Object&)
+TrySetMember(System.Dynamic.SetMemberBinder,System.Object)

diff --git a/report/System.Linq.Dynamic.Core_DynamicClassFactory.htm b/report/System.Linq.Dynamic.Core_DynamicClassFactory.htm index 56eedcc6..3c976dbe 100644 --- a/report/System.Linq.Dynamic.Core_DynamicClassFactory.htm +++ b/report/System.Linq.Dynamic.Core_DynamicClassFactory.htm @@ -15,13 +15,13 @@

Summary

Class:System.Linq.Dynamic.Core.DynamicClassFactory Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClassFactory.cs -Covered lines:200 +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClassFactory.cs +Covered lines:204 Uncovered lines:15 -Coverable lines:215 -Total lines:375 -Line coverage:93% -Branch coverage:76.4% +Coverable lines:219 +Total lines:390 +Line coverage:93.1% +Branch coverage:79.4%

Metrics

@@ -29,12 +29,13 @@

Metrics

MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage   .cctor()10100100 -CreateType(...)2813107292.577.14 +CreateType(...)266553692.578.79 +GenerateKey(...)42100100 Escape(...)10100100

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClassFactory.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicClassFactory.cs

@@ -61,7 +62,7 @@

- + @@ -103,325 +104,341 @@

- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 21    public static class DynamicClassFactory
 22    {
 23        // EmptyTypes is used to indicate that we are looking for someting without any parameters.
 124        private readonly static Type[] EmptyTypes = new Type[0];
 124        private static readonly Type[] EmptyTypes = new Type[0];
 25
 126        private static readonly ConcurrentDictionary<string, Type> GeneratedTypes = new ConcurrentDictionary<string, Typ
 27
 163        private static int _index = -1;
 64
 65        /// <summary>
 66        /// Initializes the <see cref="DynamicClassFactory"/> class.
 66        /// The AssemblyName
 67        /// </summary>
 68        static DynamicClassFactory()
 169        {
 170            var assemblyName = new AssemblyName("System.Linq.Dynamic.Core.DynamicClasses, Version=1.0.0.0");
 171            var assemblyBuilder = AssemblyBuilderFactory.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
 72
 173            ModuleBuilder = assemblyBuilder.DefineDynamicModule("System.Linq.Dynamic.Core.DynamicClasses");
 174        }
 75
 76        /// <summary>
 77        /// The CreateType method creates a new data class with a given set of public properties and returns the System.
 78        /// Data classes implement private instance variables and read/write property accessors for the specified proper
 79        /// Data classes are created in an in-memory assembly in the current application domain. All data classes inheri
 80        /// The dynamic expression parser uses the CreateClass methods to generate classes from data object initializers
 81        /// </summary>
 82        /// <param name="properties">The DynamicProperties</param>
 83        /// <param name="createParameterCtor">Create a constructor with parameters. Default set to true. Note that for L
 84        /// <returns>Type</returns>
 85        /// <example>
 86        /// <code>
 87        /// <![CDATA[
 88        /// DynamicProperty[] props = new DynamicProperty[] { new DynamicProperty("Name", typeof(string)), new DynamicPr
 89        /// Type type = DynamicClassFactory.CreateType(props);
 90        /// DynamicClass dynamicClass = Activator.CreateInstance(type) as DynamicClass;
 91        /// dynamicClass.SetDynamicProperty("Name", "Albert");
 92        /// dynamicClass.SetDynamicProperty("Birthday", new DateTime(1879, 3, 14));
 93        /// Console.WriteLine(dynamicClass);
 94        /// ]]>
 95        /// </code>
 96        /// </example>
 97        public static Type CreateType([NotNull] IList<DynamicProperty> properties, bool createParameterCtor = true)
 3498        {
 3499            Check.HasNoNulls(properties, nameof(properties));
 100
 108101            var types = properties.Select(p => p.Type).ToArray();
 108102            var names = properties.Select(p => p.Name).ToArray();
 103
 104            // Anonymous classes are generics based. The generic classes are distinguished by number of parameters and n
 105            // The specific types of the parameters are the generic arguments.
 106            // We recreate this by creating a fullName composed of all the property names, separated by a "|".
 34107            string fullName = string.Join("|", names.Select(Escape).ToArray());
 168        public static string DynamicAssemblyName = "System.Linq.Dynamic.Core.DynamicClasses, Version=1.0.0.0";
 69
 70        /// <summary>
 71        /// Initializes the <see cref="DynamicClassFactory"/> class.
 72        /// </summary>
 73        static DynamicClassFactory()
 174        {
 175            var assemblyName = new AssemblyName(DynamicAssemblyName);
 176            var assemblyBuilder = AssemblyBuilderFactory.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
 77
 178            ModuleBuilder = assemblyBuilder.DefineDynamicModule("System.Linq.Dynamic.Core.DynamicClasses");
 179        }
 80
 81        /// <summary>
 82        /// The CreateType method creates a new data class with a given set of public properties and returns the System.
 83        /// Data classes implement private instance variables and read/write property accessors for the specified proper
 84        /// Data classes are created in an in-memory assembly in the current application domain. All data classes inheri
 85        /// The dynamic expression parser uses the CreateClass methods to generate classes from data object initializers
 86        /// </summary>
 87        /// <param name="properties">The DynamicProperties</param>
 88        /// <param name="createParameterCtor">Create a constructor with parameters. Default set to true. Note that for L
 89        /// <returns>Type</returns>
 90        /// <example>
 91        /// <code>
 92        /// <![CDATA[
 93        /// DynamicProperty[] props = new DynamicProperty[] { new DynamicProperty("Name", typeof(string)), new DynamicPr
 94        /// Type type = DynamicClassFactory.CreateType(props);
 95        /// DynamicClass dynamicClass = Activator.CreateInstance(type) as DynamicClass;
 96        /// dynamicClass.SetDynamicProperty("Name", "Albert");
 97        /// dynamicClass.SetDynamicProperty("Birthday", new DateTime(1879, 3, 14));
 98        /// Console.WriteLine(dynamicClass);
 99        /// ]]>
 100        /// </code>
 101        /// </example>
 102        public static Type CreateType([NotNull] IList<DynamicProperty> properties, bool createParameterCtor = true)
 44103        {
 44104            Check.HasNoNulls(properties, nameof(properties));
 105
 136106            Type[] types = properties.Select(p => p.Type).ToArray();
 136107            string[] names = properties.Select(p => p.Name).ToArray();
 108
 109            Type type;
 44109            string key = GenerateKey(properties, createParameterCtor);
 110
 34111             if (!GeneratedTypes.TryGetValue(fullName, out type))
 34112            {
 113                // We create only a single class at a time, through this lock
 114                // Note that this is a variant of the double-checked locking.
 115                // It is safe because we are using a thread safe class.
 34116                lock (GeneratedTypes)
 34117                {
 34118                     if (!GeneratedTypes.TryGetValue(fullName, out type))
 34119                    {
 34120                        int index = Interlocked.Increment(ref _index);
 121
 34122                        string name = names.Length != 0 ? $"<>f__AnonymousType{index}`{names.Length}" : $"<>f__Anonymous
 123
 34124                        TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Public
 34125                        tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 126
 127                        GenericTypeParameterBuilder[] generics;
 128
 34129                         if (names.Length != 0)
 34130                        {
 108131                            string[] genericNames = names.Select(genericName => $"<{genericName}>j__TPar").ToArray();
 34132                            generics = tb.DefineGenericParameters(genericNames);
 250133                            foreach (GenericTypeParameterBuilder b in generics)
 74134                            {
 74135                                b.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 74136                            }
 34137                        }
 138                        else
 0139                        {
 0140                            generics = new GenericTypeParameterBuilder[0];
 0141                        }
 142
 34143                        var fields = new FieldBuilder[names.Length];
 144
 145                        // There are two for cycles because we want to have all the getter methods before all the other 
 216146                         for (int i = 0; i < names.Length; i++)
 74147                        {
 148                            // field
 74149                            fields[i] = tb.DefineField($"<{names[i]}>i__Field", generics[i].AsType(), FieldAttributes.Pr
 74150                            fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder);
 151
 74152                            PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConve
 153
 154                            // getter
 74155                            MethodBuilder getter = tb.DefineMethod($"get_{names[i]}", MethodAttributes.Public | MethodAt
 74156                            getter.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 74157                            ILGenerator ilgeneratorGetter = getter.GetILGenerator();
 74158                            ilgeneratorGetter.Emit(OpCodes.Ldarg_0);
 74159                            ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]);
 74160                            ilgeneratorGetter.Emit(OpCodes.Ret);
 74161                            property.SetGetMethod(getter);
 162
 163                            // setter
 74164                            MethodBuilder setter = tb.DefineMethod($"set_{names[i]}", MethodAttributes.Public | MethodAt
 74165                            setter.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 166
 167                            // workaround for https://github.com/dotnet/corefx/issues/7792
 74168                            setter.DefineParameter(1, ParameterAttributes.In, generics[i].Name);
 169
 74170                            ILGenerator ilgeneratorSetter = setter.GetILGenerator();
 74171                            ilgeneratorSetter.Emit(OpCodes.Ldarg_0);
 74172                            ilgeneratorSetter.Emit(OpCodes.Ldarg_1);
 74173                            ilgeneratorSetter.Emit(OpCodes.Stfld, fields[i]);
 74174                            ilgeneratorSetter.Emit(OpCodes.Ret);
 74175                            property.SetSetMethod(setter);
 74176                        }
 177
 178                        // ToString()
 34179                        MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.
 34180                        toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 34181                        ILGenerator ilgeneratorToString = toString.GetILGenerator();
 34182                        ilgeneratorToString.DeclareLocal(typeof(StringBuilder));
 34183                        ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor);
 34184                        ilgeneratorToString.Emit(OpCodes.Stloc_0);
 185
 186                        // Equals
 34187                        MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virt
 34188                        equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 34189                        equals.DefineParameter(1, ParameterAttributes.In, "value");
 190
 34191                        ILGenerator ilgeneratorEquals = equals.GetILGenerator();
 34192                        ilgeneratorEquals.DeclareLocal(tb.AsType());
 34193                        ilgeneratorEquals.Emit(OpCodes.Ldarg_1);
 34194                        ilgeneratorEquals.Emit(OpCodes.Isinst, tb.AsType());
 34195                        ilgeneratorEquals.Emit(OpCodes.Stloc_0);
 34196                        ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
 197
 34198                        Label equalsLabel = ilgeneratorEquals.DefineLabel();
 199
 200                        // GetHashCode()
 34201                        MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttri
 34202                        getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 34203                        ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator();
 34204                        ilgeneratorGetHashCode.DeclareLocal(typeof(int));
 205
 34206                         if (names.Length == 0)
 0207                        {
 0208                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0);
 0209                        }
 210                        else
 34211                        {
 212                            // As done by Roslyn
 213                            // Note that initHash can vary, because string.GetHashCode() isn't "stable" for different co
 34214                            int initHash = 0;
 215
 216216                             for (int i = 0; i < names.Length; i++)
 74217                            {
 74218                                initHash = unchecked(initHash * (-1521134295) + fields[i].Name.GetHashCode());
 74219                            }
 220
 221                            // Note that the CSC seems to generate a different seed for every anonymous class
 34222                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash);
 34223                        }
 224
 216225                         for (int i = 0; i < names.Length; i++)
 74226                        {
 74227                            Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i].AsType());
 228
 229                            // Equals()
 74230                            MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityCompa
 74231                            MethodInfo equalityComparerTEquals = TypeBuilder.GetMethod(equalityComparerT, EqualityCompar
 232
 233                            // Illegal one-byte branch at position: 9. Requested branch was: 143.
 234                            // So replace OpCodes.Brfalse_S to OpCodes.Brfalse
 74235                            ilgeneratorEquals.Emit(OpCodes.Brfalse, equalsLabel);
 74236                            ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
 74237                            ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
 74238                            ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
 74239                            ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
 74240                            ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
 74241                            ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);
 242
 243                            // GetHashCode();
 74244                            MethodInfo equalityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityC
 74245                            ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
 74246                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
 74247                            ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
 74248                            ilgeneratorGetHashCode.Emit(OpCodes.Mul);
 74249                            ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault);
 74250                            ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
 74251                            ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]);
 74252                            ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, equalityComparerTGetHashCode);
 74253                            ilgeneratorGetHashCode.Emit(OpCodes.Add);
 254
 255                            // ToString();
 74256                            ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 74257                            ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? $"{{ {names[i]} = " : $", {names[i]} = ");
 74258                            ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
 74259                            ilgeneratorToString.Emit(OpCodes.Pop);
 74260                            ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 74261                            ilgeneratorToString.Emit(OpCodes.Ldarg_0);
 74262                            ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]);
 74263                            ilgeneratorToString.Emit(OpCodes.Box, generics[i].AsType());
 74264                            ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject);
 74265                            ilgeneratorToString.Emit(OpCodes.Pop);
 74266                        }
 267
 34268                         if (createParameterCtor)
 27269                        {
 270                            // .ctor default
 27271                            ConstructorBuilder constructorDef = tb.DefineConstructor(MethodAttributes.Public | MethodAtt
 27272                            constructorDef.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 273
 27274                            ILGenerator ilgeneratorConstructorDef = constructorDef.GetILGenerator();
 27275                            ilgeneratorConstructorDef.Emit(OpCodes.Ldarg_0);
 27276                            ilgeneratorConstructorDef.Emit(OpCodes.Call, ObjectCtor);
 27277                            ilgeneratorConstructorDef.Emit(OpCodes.Ret);
 278
 279                            // .ctor with params
 86280                            ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttrib
 27281                            constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 282
 27283                            ILGenerator ilgeneratorConstructor = constructor.GetILGenerator();
 27284                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
 27285                            ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor);
 286
 172287                             for (int i = 0; i < names.Length; i++)
 59288                            {
 59289                                constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]);
 59290                                ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
 291
 59292                                 if (i == 0)
 27293                                {
 27294                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_1);
 27295                                }
 32296                                 else if (i == 1)
 18297                                {
 18298                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_2);
 18299                                }
 14300                                 else if (i == 2)
 5301                                {
 5302                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_3);
 5303                                }
 9304                                 else if (i < 255)
 9305                                {
 9306                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1));
 9307                                }
 308                                else
 0309                                {
 310                                    // Ldarg uses a ushort, but the Emit only accepts short, so we use a unchecked(...),
 0311                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked((short)(i + 1)));
 0312                                }
 313
 59314                                ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]);
 59315                            }
 316
 27317                            ilgeneratorConstructor.Emit(OpCodes.Ret);
 27318                        }
 319
 320                        // Equals()
 34321                         if (names.Length == 0)
 0322                        {
 0323                            ilgeneratorEquals.Emit(OpCodes.Ldnull);
 0324                            ilgeneratorEquals.Emit(OpCodes.Ceq);
 0325                            ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
 0326                            ilgeneratorEquals.Emit(OpCodes.Ceq);
 0327                        }
 328                        else
 34329                        {
 34330                            ilgeneratorEquals.Emit(OpCodes.Ret);
 34331                            ilgeneratorEquals.MarkLabel(equalsLabel);
 34332                            ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
 34333                        }
 334
 34335                        ilgeneratorEquals.Emit(OpCodes.Ret);
 336
 337                        // GetHashCode()
 34338                        ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
 34339                        ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
 34340                        ilgeneratorGetHashCode.Emit(OpCodes.Ret);
 341
 342                        // ToString()
 34343                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 34344                         ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }");
 34345                        ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
 34346                        ilgeneratorToString.Emit(OpCodes.Pop);
 34347                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 34348                        ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString);
 34349                        ilgeneratorToString.Emit(OpCodes.Ret);
 350
 34351                        type = tb.CreateType();
 352
 34353                         type = GeneratedTypes.GetOrAdd(fullName + "|_" + (createParameterCtor ? "1" : "0"), type);
 34354                    }
 34355                }
 34356            }
 357
 34358             if (types.Length != 0)
 34359            {
 34360                type = type.MakeGenericType(types);
 34361            }
 362
 34363            return type;
 34364        }
 365
 366        private static string Escape(string str)
 74367        {
 368            // We escape the \ with \\, so that we can safely escape the "|" (that we use as a separator) with "\|"
 74369            str = str.Replace(@"\", @"\\");
 74370            str = str.Replace(@"|", @"\|");
 74371            return str;
 74372        }
 373    }
 374}
 375#endif
 111            Type type;
 44112             if (!GeneratedTypes.TryGetValue(key, out type))
 30113            {
 114                // We create only a single class at a time, through this lock
 115                // Note that this is a variant of the double-checked locking.
 116                // It is safe because we are using a thread safe class.
 30117                lock (GeneratedTypes)
 30118                {
 30119                     if (!GeneratedTypes.TryGetValue(key, out type))
 30120                    {
 30121                        int index = Interlocked.Increment(ref _index);
 122
 30123                        string name = names.Length != 0 ? $"<>f__AnonymousType{index}`{names.Length}" : $"<>f__Anonymous
 124
 30125                        TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Public
 30126                        tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 127
 128                        GenericTypeParameterBuilder[] generics;
 129
 30130                         if (names.Length != 0)
 30131                        {
 99132                            string[] genericNames = names.Select(genericName => $"<{genericName}>j__TPar").ToArray();
 30133                            generics = tb.DefineGenericParameters(genericNames);
 228134                            foreach (GenericTypeParameterBuilder b in generics)
 69135                            {
 69136                                b.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 69137                            }
 30138                        }
 139                        else
 0140                        {
 0141                            generics = new GenericTypeParameterBuilder[0];
 0142                        }
 143
 30144                        var fields = new FieldBuilder[names.Length];
 145
 146                        // There are two for cycles because we want to have all the getter methods before all the other 
 198147                         for (int i = 0; i < names.Length; i++)
 69148                        {
 149                            // field
 69150                            fields[i] = tb.DefineField($"<{names[i]}>i__Field", generics[i].AsType(), FieldAttributes.Pr
 69151                            fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder);
 152
 69153                            PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConve
 154
 155                            // getter
 69156                            MethodBuilder getter = tb.DefineMethod($"get_{names[i]}", MethodAttributes.Public | MethodAt
 69157                            getter.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 69158                            ILGenerator ilgeneratorGetter = getter.GetILGenerator();
 69159                            ilgeneratorGetter.Emit(OpCodes.Ldarg_0);
 69160                            ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]);
 69161                            ilgeneratorGetter.Emit(OpCodes.Ret);
 69162                            property.SetGetMethod(getter);
 163
 164                            // setter
 69165                            MethodBuilder setter = tb.DefineMethod($"set_{names[i]}", MethodAttributes.Public | MethodAt
 69166                            setter.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
 167
 168                            // workaround for https://github.com/dotnet/corefx/issues/7792
 69169                            setter.DefineParameter(1, ParameterAttributes.In, generics[i].Name);
 170
 69171                            ILGenerator ilgeneratorSetter = setter.GetILGenerator();
 69172                            ilgeneratorSetter.Emit(OpCodes.Ldarg_0);
 69173                            ilgeneratorSetter.Emit(OpCodes.Ldarg_1);
 69174                            ilgeneratorSetter.Emit(OpCodes.Stfld, fields[i]);
 69175                            ilgeneratorSetter.Emit(OpCodes.Ret);
 69176                            property.SetSetMethod(setter);
 69177                        }
 178
 179                        // ToString()
 30180                        MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.
 30181                        toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 30182                        ILGenerator ilgeneratorToString = toString.GetILGenerator();
 30183                        ilgeneratorToString.DeclareLocal(typeof(StringBuilder));
 30184                        ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor);
 30185                        ilgeneratorToString.Emit(OpCodes.Stloc_0);
 186
 187                        // Equals
 30188                        MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virt
 30189                        equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 30190                        equals.DefineParameter(1, ParameterAttributes.In, "value");
 191
 30192                        ILGenerator ilgeneratorEquals = equals.GetILGenerator();
 30193                        ilgeneratorEquals.DeclareLocal(tb.AsType());
 30194                        ilgeneratorEquals.Emit(OpCodes.Ldarg_1);
 30195                        ilgeneratorEquals.Emit(OpCodes.Isinst, tb.AsType());
 30196                        ilgeneratorEquals.Emit(OpCodes.Stloc_0);
 30197                        ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
 198
 30199                        Label equalsLabel = ilgeneratorEquals.DefineLabel();
 200
 201                        // GetHashCode()
 30202                        MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttri
 30203                        getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 30204                        ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator();
 30205                        ilgeneratorGetHashCode.DeclareLocal(typeof(int));
 206
 30207                         if (names.Length == 0)
 0208                        {
 0209                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0);
 0210                        }
 211                        else
 30212                        {
 213                            // As done by Roslyn
 214                            // Note that initHash can vary, because string.GetHashCode() isn't "stable" for different co
 30215                            int initHash = 0;
 216
 198217                             for (int i = 0; i < names.Length; i++)
 69218                            {
 69219                                initHash = unchecked(initHash * (-1521134295) + fields[i].Name.GetHashCode());
 69220                            }
 221
 222                            // Note that the CSC seems to generate a different seed for every anonymous class
 30223                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash);
 30224                        }
 225
 198226                         for (int i = 0; i < names.Length; i++)
 69227                        {
 69228                            Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i].AsType());
 229
 230                            // Equals()
 69231                            MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityCompa
 69232                            MethodInfo equalityComparerTEquals = TypeBuilder.GetMethod(equalityComparerT, EqualityCompar
 233
 234                            // Illegal one-byte branch at position: 9. Requested branch was: 143.
 235                            // So replace OpCodes.Brfalse_S to OpCodes.Brfalse
 69236                            ilgeneratorEquals.Emit(OpCodes.Brfalse, equalsLabel);
 69237                            ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
 69238                            ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
 69239                            ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
 69240                            ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
 69241                            ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
 69242                            ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);
 243
 244                            // GetHashCode();
 69245                            MethodInfo equalityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityC
 69246                            ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
 69247                            ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
 69248                            ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
 69249                            ilgeneratorGetHashCode.Emit(OpCodes.Mul);
 69250                            ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault);
 69251                            ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
 69252                            ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]);
 69253                            ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, equalityComparerTGetHashCode);
 69254                            ilgeneratorGetHashCode.Emit(OpCodes.Add);
 255
 256                            // ToString();
 69257                            ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 69258                            ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? $"{{ {names[i]} = " : $", {names[i]} = ");
 69259                            ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
 69260                            ilgeneratorToString.Emit(OpCodes.Pop);
 69261                            ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 69262                            ilgeneratorToString.Emit(OpCodes.Ldarg_0);
 69263                            ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]);
 69264                            ilgeneratorToString.Emit(OpCodes.Box, generics[i].AsType());
 69265                            ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject);
 69266                            ilgeneratorToString.Emit(OpCodes.Pop);
 69267                        }
 268
 30269                         if (createParameterCtor)
 23270                        {
 271                            // .ctor default
 23272                            ConstructorBuilder constructorDef = tb.DefineConstructor(MethodAttributes.Public | MethodAtt
 23273                            constructorDef.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 274
 23275                            ILGenerator ilgeneratorConstructorDef = constructorDef.GetILGenerator();
 23276                            ilgeneratorConstructorDef.Emit(OpCodes.Ldarg_0);
 23277                            ilgeneratorConstructorDef.Emit(OpCodes.Call, ObjectCtor);
 23278                            ilgeneratorConstructorDef.Emit(OpCodes.Ret);
 279
 280                            // .ctor with params
 77281                            ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttrib
 23282                            constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
 283
 23284                            ILGenerator ilgeneratorConstructor = constructor.GetILGenerator();
 23285                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
 23286                            ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor);
 287
 154288                             for (int i = 0; i < names.Length; i++)
 54289                            {
 54290                                constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]);
 54291                                ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
 292
 54293                                 if (i == 0)
 23294                                {
 23295                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_1);
 23296                                }
 31297                                 else if (i == 1)
 16298                                {
 16299                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_2);
 16300                                }
 15301                                 else if (i == 2)
 6302                                {
 6303                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_3);
 6304                                }
 9305                                 else if (i < 255)
 9306                                {
 9307                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1));
 9308                                }
 309                                else
 0310                                {
 311                                    // Ldarg uses a ushort, but the Emit only accepts short, so we use a unchecked(...),
 0312                                    ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked((short)(i + 1)));
 0313                                }
 314
 54315                                ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]);
 54316                            }
 317
 23318                            ilgeneratorConstructor.Emit(OpCodes.Ret);
 23319                        }
 320
 321                        // Equals()
 30322                         if (names.Length == 0)
 0323                        {
 0324                            ilgeneratorEquals.Emit(OpCodes.Ldnull);
 0325                            ilgeneratorEquals.Emit(OpCodes.Ceq);
 0326                            ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
 0327                            ilgeneratorEquals.Emit(OpCodes.Ceq);
 0328                        }
 329                        else
 30330                        {
 30331                            ilgeneratorEquals.Emit(OpCodes.Ret);
 30332                            ilgeneratorEquals.MarkLabel(equalsLabel);
 30333                            ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
 30334                        }
 335
 30336                        ilgeneratorEquals.Emit(OpCodes.Ret);
 337
 338                        // GetHashCode()
 30339                        ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
 30340                        ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
 30341                        ilgeneratorGetHashCode.Emit(OpCodes.Ret);
 342
 343                        // ToString()
 30344                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 30345                         ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }");
 30346                        ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
 30347                        ilgeneratorToString.Emit(OpCodes.Pop);
 30348                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
 30349                        ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString);
 30350                        ilgeneratorToString.Emit(OpCodes.Ret);
 351
 30352                        type = tb.CreateType();
 353
 30354                        type = GeneratedTypes.GetOrAdd(key, type);
 30355                    }
 30356                }
 30357            }
 358
 44359             if (types.Length != 0)
 44360            {
 44361                type = type.MakeGenericType(types);
 44362            }
 363
 44364            return type;
 44365        }
 366
 367        /// <summary>
 368        /// Generates the key.
 369        /// Anonymous classes are generics based. The generic classes are distinguished by number of parameters and name
 370        /// </summary>
 371        /// <param name="dynamicProperties">The dynamic propertys.</param>
 372        /// <param name="createParameterCtor">if set to <c>true</c> [create parameter ctor].</param>
 373        /// <returns></returns>
 374        private static string GenerateKey(IEnumerable<DynamicProperty> dynamicProperties, bool createParameterCtor)
 44375        {
 376            // We recreate this by creating a fullName composed of all the property names and types, separated by a "|".
 377            // And append and extra field depending on createParameterCtor.
 136378             return string.Format("{0}_{1}", string.Join("|", dynamicProperties.Select(p => Escape(p.Name) + "~" + p.Type
 44379        }
 380
 381        private static string Escape(string str)
 92382        {
 383            // We escape the \ with \\, so that we can safely escape the "|" (that we use as a separator) with "\|"
 92384            str = str.Replace(@"\", @"\\");
 92385            str = str.Replace(@"|", @"\|");
 92386            return str;
 92387        }
 388    }
 389}
 390#endif
- +

Methods/Properties

.cctor()
-CreateType(System.Collections.Generic.IList`1<System.Linq.Dynamic.Core.DynamicProperty>,System.Boolean)
-Escape(System.String)
+CreateType(System.Collections.Generic.IList`1<System.Linq.Dynamic.Core.DynamicProperty>,System.Boolean)
+GenerateKey(System.Collections.Generic.IEnumerable`1<System.Linq.Dynamic.Core.DynamicProperty>,System.Boolean)
+Escape(System.String)

diff --git a/report/System.Linq.Dynamic.Core_DynamicEnumerableAsyncExtensions.htm b/report/System.Linq.Dynamic.Core_DynamicEnumerableAsyncExtensions.htm new file mode 100644 index 00000000..1b0ada99 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_DynamicEnumerableAsyncExtensions.htm @@ -0,0 +1,168 @@ + + + + + +System.Linq.Dynamic.Core.DynamicEnumerableAsyncExtensions - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.DynamicEnumerableAsyncExtensions
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicEnumerableAsyncExtensions.cs
Covered lines:0
Uncovered lines:32
Coverable lines:32
Total lines:106
Line coverage:0%
+

Metrics

+ + + + + + + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
ToDynamicArrayAsync(...)1000
ToDynamicArrayAsync(...)1000
ToDynamicArrayAsync(...)1000
ToDynamicListAsync(...)1000
ToDynamicListAsync(...)1000
ToDynamicListAsync(...)1000
CastToArrayAsync(...)1000
CastToListAsync(...)1000
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicEnumerableAsyncExtensions.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1#if !(NET35 || NET40)
 2using JetBrains.Annotations;
 3using System.Collections;
 4using System.Collections.Generic;
 5using System.Linq.Dynamic.Core.Validation;
 6using System.Threading.Tasks;
 7
 8namespace System.Linq.Dynamic.Core
 9{
 10    /// <summary>
 11    /// Define async extensions on <see cref="IEnumerable"/>.
 12    /// </summary>
 13    public static class DynamicEnumerableAsyncExtensions
 14    {
 15        /// <summary>
 16        /// Async creates an array of dynamic objects from a <see cref="IEnumerable"/>.
 17        /// </summary>
 18        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 19        /// <param name="type">A <see cref="Type"/> cast to.</param>
 20        /// <returns>An Array that contains the elements from the input sequence.</returns>
 21        [PublicAPI]
 22        public static Task<dynamic[]> ToDynamicArrayAsync([NotNull] this IEnumerable source, [NotNull] Type type)
 023        {
 024            Check.NotNull(source, nameof(source));
 025            Check.NotNull(type, nameof(type));
 26
 027            return Task.Run(() => source.ToDynamicArray());
 028        }
 29
 30        /// <summary>
 31        /// Async creates an array of dynamic objects from a <see cref="IEnumerable"/>.
 32        /// </summary>
 33        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 34        /// <returns>An array that contains the elements from the input sequence.</returns>
 35        [PublicAPI]
 36        public static Task<dynamic[]> ToDynamicArrayAsync([NotNull] this IEnumerable source)
 037        {
 038            Check.NotNull(source, nameof(source));
 039            return CastToArrayAsync<dynamic>(source);
 040        }
 41
 42        /// <summary>
 43        /// Async creates an array of dynamic objects from a <see cref="IEnumerable"/>.
 44        /// </summary>
 45        /// <typeparam name="T">The generic type.</typeparam>
 46        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 47        /// <returns>An Array{T} that contains the elements from the input sequence.</returns>
 48        [PublicAPI]
 49        public static Task<T[]> ToDynamicArrayAsync<T>([NotNull] this IEnumerable source)
 050        {
 051            Check.NotNull(source, nameof(source));
 052            return CastToArrayAsync<T>(source);
 053        }
 54
 55        /// <summary>
 56        /// Async creates a list of dynamic objects from a <see cref="IEnumerable"/>.
 57        /// </summary>
 58        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 59        /// <param name="type">A <see cref="Type"/> cast to.</param>
 60        /// <returns>An List that contains the elements from the input sequence.</returns>
 61        [PublicAPI]
 62        public static Task<List<dynamic>> ToDynamicListAsync([NotNull] this IEnumerable source, [NotNull] Type type)
 063        {
 064            Check.NotNull(source, nameof(source));
 065            Check.NotNull(type, nameof(type));
 66
 067            return Task.Run(() => source.ToDynamicList());
 068        }
 69
 70        /// <summary>
 71        /// Async creates a list of dynamic objects from a <see cref="IEnumerable"/>.
 72        /// </summary>
 73        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 74        /// <returns>A List that contains the elements from the input sequence.</returns>
 75        [PublicAPI]
 76        public static Task<List<dynamic>> ToDynamicListAsync([NotNull] this IEnumerable source)
 077        {
 078            Check.NotNull(source, nameof(source));
 079            return CastToListAsync<dynamic>(source);
 080        }
 81
 82        /// <summary>
 83        /// Async creates a list of dynamic objects from an <see cref="IEnumerable"/>.
 84        /// </summary>
 85        /// <typeparam name="T">Generic Type</typeparam>
 86        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 87        /// <returns>A List{T} that contains the elements from the input sequence.</returns>
 88        [PublicAPI]
 89        public static Task<List<T>> ToDynamicListAsync<T>([NotNull] this IEnumerable source)
 090        {
 091            Check.NotNull(source, nameof(source));
 092            return CastToListAsync<T>(source);
 093        }
 94
 95        private static Task<T[]> CastToArrayAsync<T>(IEnumerable source)
 096        {
 097            return Task.Run(() => DynamicEnumerableExtensions.CastToArray<T>(source));
 098        }
 99
 100        private static Task<List<T>> CastToListAsync<T>(IEnumerable source)
 0101        {
 0102            return Task.Run(() => DynamicEnumerableExtensions.CastToList<T>(source));
 0103        }
 104    }
 105}
 106#endif
+
+
+ +
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_DynamicEnumerableExtensions.htm b/report/System.Linq.Dynamic.Core_DynamicEnumerableExtensions.htm index 2998bd04..f5d5598c 100644 --- a/report/System.Linq.Dynamic.Core_DynamicEnumerableExtensions.htm +++ b/report/System.Linq.Dynamic.Core_DynamicEnumerableExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.DynamicEnumerableExtensions Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicEnumerableExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicEnumerableExtensions.cs Covered lines:37 Uncovered lines:0 Coverable lines:37 @@ -39,7 +39,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicEnumerableExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicEnumerableExtensions.cs

@@ -77,10 +77,10 @@

- - - - + + + + @@ -90,10 +90,10 @@

- - - - + + + + @@ -106,17 +106,17 @@

- - - + + + - + - + - + - + @@ -148,12 +148,12 @@

- - - + + + - - + + @@ -167,12 +167,12 @@

- - - - + + + + - + @@ -180,7 +180,7 @@

#LineLine coverage
 32        }
 33#else
 34        public static dynamic[] ToDynamicArray([NotNull] this IEnumerable source)
 1635        {
 1636            Check.NotNull(source, nameof(source));
 1637            return CastToArray<dynamic>(source);
 1638        }
 1935        {
 1936            Check.NotNull(source, nameof(source));
 1937            return CastToArray<dynamic>(source);
 1938        }
 39#endif
 40
 41        /// <summary>
 45        /// <param name="source">A <see cref="IEnumerable"/> to create an array from.</param>
 46        /// <returns>An Array{T} that contains the elements from the input sequence.</returns>
 47        public static T[] ToDynamicArray<T>([NotNull] this IEnumerable source)
 2148        {
 2149            Check.NotNull(source, nameof(source));
 2150            return CastToArray<T>(source);
 2151        }
 3748        {
 3749            Check.NotNull(source, nameof(source));
 3750            return CastToArray<T>(source);
 3751        }
 52
 53        /// <summary>
 54        /// Creates an array of dynamic objects from a <see cref="IEnumerable"/>.
 61#else
 62        public static dynamic[] ToDynamicArray([NotNull] this IEnumerable source, [NotNull] Type type)
 63#endif
 264        {
 265            Check.NotNull(source, nameof(source));
 266            Check.NotNull(type, nameof(type));
 564        {
 565            Check.NotNull(source, nameof(source));
 566            Check.NotNull(type, nameof(type));
 67
 268            object result = ToDynamicArrayGenericMethod.MakeGenericMethod(type).Invoke(source, new object[] { source });
 568            IEnumerable result = (IEnumerable)ToDynamicArrayGenericMethod.MakeGenericMethod(type).Invoke(source, new obj
 69#if NET35
 70            return (object[])result;
 70            return CastToArray<object>(result);
 71#else
 272            return (dynamic[]) result;
 572            return CastToArray<dynamic>(result);
 73#endif
 274        }
 574        }
 75
 76        /// <summary>
 77        /// Creates a list of dynamic objects from a <see cref="IEnumerable"/>.
 103#else
 104        public static List<dynamic> ToDynamicList([NotNull] this IEnumerable source, [NotNull] Type type)
 105#endif
 1106        {
 1107            Check.NotNull(source, nameof(source));
 1108            Check.NotNull(type, nameof(type));
 4106        {
 4107            Check.NotNull(source, nameof(source));
 4108            Check.NotNull(type, nameof(type));
 109
 1110            return ToDynamicArray(source, type).ToList();
 1111        }
 4110            return ToDynamicArray(source, type).ToList();
 4111        }
 112
 113        /// <summary>
 114        /// Creates a list of dynamic objects from a <see cref="IEnumerable"/>.
 7122            return CastToList<T>(source);
 7123        }
 124
 125        private static T[] CastToArray<T>(IEnumerable source)
 37126        {
 37127            return source.Cast<T>().ToArray();
 37128        }
 125        internal static T[] CastToArray<T>(IEnumerable source)
 61126        {
 61127            return source.Cast<T>().ToArray();
 61128        }
 129
 130        private static List<T> CastToList<T>(IEnumerable source)
 130        internal static List<T> CastToList<T>(IEnumerable source)
 21131        {
 21132            return source.Cast<T>().ToList();
 21133        }
 135}
- +

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_DynamicExpressionParser.htm b/report/System.Linq.Dynamic.Core_DynamicExpressionParser.htm index e9fc01d8..4e5aa7ac 100644 --- a/report/System.Linq.Dynamic.Core_DynamicExpressionParser.htm +++ b/report/System.Linq.Dynamic.Core_DynamicExpressionParser.htm @@ -15,153 +15,301 @@

Summary

Class:System.Linq.Dynamic.Core.DynamicExpressionParser Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs -Covered lines:26 -Uncovered lines:0 -Coverable lines:26 -Total lines:110 -Line coverage:100% +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs +Covered lines:38 +Uncovered lines:16 +Coverable lines:54 +Total lines:242 +Line coverage:70.3%

Metrics

+ + + + + + + - - + + - + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
ParseLambda(...)10100100
ParseLambda(...)1000
ParseLambda(...)10100100
ParseLambda(...)1000
ParseLambda(...)10100100
ParseLambda(...)1000
ParseLambda(...)10100100
ParseLambda(...)10100100
ParseLambda(...)10100100
ParseLambda(...)10100100
ParseLambda(...)10100100
ParseLambda(...)1000
ParseLambda(...)10100100
ParseLambda(...)10100100
ParseLambda(...)20100100
ParseLambda(...)1000
ParseLambda(...)10100100

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using JetBrains.Annotations;
 2using System.Linq.Dynamic.Core.Validation;
 3using System.Linq.Expressions;
 4
 5namespace System.Linq.Dynamic.Core
 6{
 7    /// <summary>
 8    /// Helper class to convert an expression into an LambdaExpression
 9    /// </summary>
 10    public static class DynamicExpressionParser
 11    {
 12        /// <summary>
 13        /// Parses a expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that th
 14        /// </summary>
 15        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 16        /// <param name="expression">The expression.</param>
 17        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 18        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 19        [PublicAPI]
 20        public static LambdaExpression ParseLambda([CanBeNull] Type resultType, [NotNull] string expression, params obje
 321        {
 322            return ParseLambda(true, resultType, expression, values);
 323        }
 24
 25        /// <summary>
 26        /// Parses a expression into a LambdaExpression.
 27        /// </summary>
 28        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 29        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 30        /// <param name="expression">The expression.</param>
 31        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 32        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 33        [PublicAPI]
 34        public static LambdaExpression ParseLambda(bool createParameterCtor, [CanBeNull] Type resultType, [NotNull] stri
 335        {
 336            Check.NotEmpty(expression, nameof(expression));
 37
 338            var parser = new ExpressionParser(new ParameterExpression[0], expression, values);
 39
 340            return Expression.Lambda(parser.Parse(resultType, true));
 341        }
 42
 43        /// <summary>
 44        /// Parses a expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that th
 45        /// </summary>
 46        /// <param name="itType">The main type from the dynamic class expression.</param>
 47        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 48        /// <param name="expression">The expression.</param>
 49        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 50        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 51        [PublicAPI]
 52        public static LambdaExpression ParseLambda([NotNull] Type itType, [CanBeNull] Type resultType, [NotNull] string 
 153        {
 154            return ParseLambda(true, itType, resultType, expression, values);
 155        }
 56
 57        /// <summary>
 58        /// Parses a expression into a LambdaExpression.
 59        /// </summary>
 60        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 61        /// <param name="itType">The main type from the dynamic class expression.</param>
 62        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 63        /// <param name="expression">The expression.</param>
 64        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 65        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 66        [PublicAPI]
 67        public static LambdaExpression ParseLambda(bool createParameterCtor, [NotNull] Type itType, [CanBeNull] Type res
 33568        {
 33569            Check.NotNull(itType, nameof(itType));
 33570            Check.NotEmpty(expression, nameof(expression));
 71
 33572            return ParseLambda(createParameterCtor, new[] { Expression.Parameter(itType, "") }, resultType, expression, 
 30373        }
 74
 75        /// <summary>
 76        /// Parses a expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that th
 77        /// </summary>
 78        /// <param name="parameters">A array from ParameterExpressions.</param>
 79        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 80        /// <param name="expression">The expression.</param>
 81        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 82        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 83        [PublicAPI]
 84        public static LambdaExpression ParseLambda([NotNull] ParameterExpression[] parameters, [CanBeNull] Type resultTy
 685        {
 686            return ParseLambda(true, parameters, resultType, expression, values);
 587        }
 88
 89        /// <summary>
 90        /// Parses a expression into a LambdaExpression.
 91        /// </summary>
 92        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 93        /// <param name="parameters">A array from ParameterExpressions.</param>
 94        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 95        /// <param name="expression">The expression.</param>
 96        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 97        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 98        [PublicAPI]
 99        public static LambdaExpression ParseLambda(bool createParameterCtor, [NotNull] ParameterExpression[] parameters,
 348100        {
 348101            Check.NotEmpty(parameters, nameof(parameters));
 1049102            Check.Condition(parameters, p => p.Count(x => x == null) == 0, nameof(parameters));
 348103            Check.NotEmpty(expression, nameof(expression));
 104
 348105            var parser = new ExpressionParser(parameters, expression, values);
 106
 348107            return Expression.Lambda(parser.Parse(resultType, createParameterCtor), parameters);
 315108        }
 109    }
 110}
 1using System.Linq.Dynamic.Core.Parser;
 2using JetBrains.Annotations;
 3using System.Linq.Dynamic.Core.Validation;
 4using System.Linq.Expressions;
 5
 6namespace System.Linq.Dynamic.Core
 7{
 8    /// <summary>
 9    /// Helper class to convert an expression into an LambdaExpression
 10    /// </summary>
 11    public static class DynamicExpressionParser
 12    {
 13        /// <summary>
 14        /// *** Parses an expression into a LambdaExpression.
 15        /// </summary>
 16        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 17        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 18        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 19        /// <param name="expression">The expression.</param>
 20        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 21        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 22        [PublicAPI]
 23        public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConfig, bool createParameterCtor, [C
 424        {
 425            Check.NotEmpty(expression, nameof(expression));
 26
 427            var parser = new ExpressionParser(new ParameterExpression[0], expression, values, parsingConfig);
 28
 429            return Expression.Lambda(parser.Parse(resultType, createParameterCtor));
 430        }
 31
 32        /// <summary>
 33        /// Parses an expression into a Typed Expression.
 34        /// </summary>
 35        /// <typeparam name="TResult">The type of the result.</typeparam>
 36        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 37        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 38        /// <param name="expression">The expression.</param>
 39        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 40        /// <returns>The generated <see cref="Expression"/></returns>
 41        [PublicAPI]
 42        public static Expression<Func<TResult>> ParseLambda<TResult>([CanBeNull] ParsingConfig parsingConfig, bool creat
 043        {
 044            return (Expression<Func<TResult>>)ParseLambda(parsingConfig, createParameterCtor, typeof(TResult), expressio
 045        }
 46
 47        /// <summary>
 48        /// *** Parses an expression into a LambdaExpression.
 49        /// </summary>
 50        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 51        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 52        /// <param name="parameters">A array from ParameterExpressions.</param>
 53        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 54        /// <param name="expression">The expression.</param>
 55        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 56        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 57        [PublicAPI]
 58        public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConfig, bool createParameterCtor, [N
 46459        {
 46460            Check.NotNull(parameters, nameof(parameters));
 46461            Check.HasNoNulls(parameters, nameof(parameters));
 46462            Check.NotEmpty(expression, nameof(expression));
 63
 46464            var parser = new ExpressionParser(parameters, expression, values, parsingConfig);
 65
 46366            return Expression.Lambda(parser.Parse(resultType, createParameterCtor), parameters);
 43067        }
 68
 69        /// <summary>
 70        /// Parses an expression into a Typed Expression.
 71        /// </summary>
 72        /// <typeparam name="TResult">The type of the result.</typeparam>
 73        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 74        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 75        /// <param name="parameters">A array from ParameterExpressions.</param>
 76        /// <param name="expression">The expression.</param>
 77        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 78        /// <returns>The generated <see cref="Expression"/></returns>
 79        [PublicAPI]
 80        public static Expression<Func<TResult>> ParseLambda<TResult>([CanBeNull] ParsingConfig parsingConfig, bool creat
 081        {
 082            return (Expression<Func<TResult>>)ParseLambda(parsingConfig, createParameterCtor, parameters, typeof(TResult
 083        }
 84
 85        /// <summary>
 86        /// Parses an expression into a LambdaExpression.
 87        /// </summary>
 88        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 89        /// <param name="itType">The main type from the dynamic class expression.</param>
 90        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 91        /// <param name="expression">The expression.</param>
 92        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 93        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 94        [PublicAPI]
 95        public static LambdaExpression ParseLambda(bool createParameterCtor, [NotNull] Type itType, [CanBeNull] Type res
 1796        {
 1797            Check.NotNull(itType, nameof(itType));
 1798            Check.NotEmpty(expression, nameof(expression));
 99
 17100            return ParseLambda(createParameterCtor, new[] { ParameterExpressionHelper.CreateParameterExpression(itType, 
 16101        }
 102
 103        /// <summary>
 104        /// Parses an expression into a Typed Expression.
 105        /// </summary>
 106        /// <typeparam name="T">The `it`-Type.</typeparam>
 107        /// <typeparam name="TResult">The type of the result.</typeparam>
 108        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 109        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 110        /// <param name="expression">The expression.</param>
 111        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 112        /// <returns>The generated <see cref="Expression"/></returns>
 113        [PublicAPI]
 114        public static Expression<Func<T, TResult>> ParseLambda<T, TResult>([CanBeNull] ParsingConfig parsingConfig, bool
 0115        {
 0116            Check.NotEmpty(expression, nameof(expression));
 117
 0118            return (Expression<Func<T, TResult>>)ParseLambda(parsingConfig, createParameterCtor, new[] { ParameterExpres
 0119        }
 120
 121        /// <summary>
 122        /// Parses an expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that t
 123        /// </summary>
 124        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 125        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 126        /// <param name="expression">The expression.</param>
 127        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 128        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 129        [PublicAPI]
 130        public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConfig, [CanBeNull] Type resultType,
 1131        {
 1132            return ParseLambda(parsingConfig, true, resultType, expression, values);
 1133        }
 134
 135        /// <summary>
 136        /// Parses an expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that t
 137        /// </summary>
 138        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 139        /// <param name="expression">The expression.</param>
 140        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 141        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 142        [PublicAPI]
 143        public static LambdaExpression ParseLambda([CanBeNull] Type resultType, [NotNull] string expression, params obje
 3144        {
 3145            Check.NotEmpty(expression, nameof(expression));
 146
 3147            return ParseLambda(null, true, resultType, expression, values);
 3148        }
 149
 150        /// <summary>
 151        /// Parses an expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that t
 152        /// </summary>
 153        /// <param name="itType">The main type from the dynamic class expression.</param>
 154        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 155        /// <param name="expression">The expression.</param>
 156        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 157        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 158        [PublicAPI]
 159        public static LambdaExpression ParseLambda([NotNull] Type itType, [CanBeNull] Type resultType, string expression
 5160        {
 5161            return ParseLambda(true, itType, resultType, expression, values);
 4162        }
 163
 164        /// <summary>
 165        /// Parses an expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that t
 166        /// </summary>
 167        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 168        /// <param name="itType">The main type from the dynamic class expression.</param>
 169        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 170        /// <param name="expression">The expression.</param>
 171        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 172        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 173        [PublicAPI]
 174        public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConfig, [NotNull] Type itType, [CanB
 0175        {
 0176            return ParseLambda(true, itType, resultType, expression, parsingConfig, values);
 0177        }
 178
 179        /// <summary>
 180        /// Parses an expression into a LambdaExpression.
 181        /// </summary>
 182        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 183        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 184        /// <param name="itType">The main type from the dynamic class expression.</param>
 185        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 186        /// <param name="expression">The expression.</param>
 187        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 188        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 189        [PublicAPI]
 190        public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConfig, bool createParameterCtor, [N
 418191        {
 418192            Check.NotNull(itType, nameof(itType));
 418193            Check.NotEmpty(expression, nameof(expression));
 194
 418195            return ParseLambda(parsingConfig, createParameterCtor, new[] { ParameterExpressionHelper.CreateParameterExpr
 387196        }
 197
 198        /// <summary>
 199        /// Parses an expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that t
 200        /// </summary>
 201        /// <param name="parameters">A array from ParameterExpressions.</param>
 202        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 203        /// <param name="expression">The expression.</param>
 204        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 205        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 206        [PublicAPI]
 207        public static LambdaExpression ParseLambda([NotNull] ParameterExpression[] parameters, [CanBeNull] Type resultTy
 17208        {
 17209            return ParseLambda(null, true, parameters, resultType, expression, values);
 15210        }
 211
 212        /// <summary>
 213        /// Parses an expression into a LambdaExpression. (Also create a constructor for all the parameters. Note that t
 214        /// </summary>
 215        /// <param name="parsingConfig">The Configuration for the parsing.</param>
 216        /// <param name="parameters">A array from ParameterExpressions.</param>
 217        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 218        /// <param name="expression">The expression.</param>
 219        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 220        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 221        [PublicAPI]
 222        public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConfig, [NotNull] ParameterExpressio
 0223        {
 0224            return ParseLambda(parsingConfig, true, parameters, resultType, expression, values);
 0225        }
 226
 227        /// <summary>
 228        /// Parses an expression into a LambdaExpression.
 229        /// </summary>
 230        /// <param name="createParameterCtor">if set to <c>true</c> then also create a constructor for all the parameter
 231        /// <param name="parameters">A array from ParameterExpressions.</param>
 232        /// <param name="resultType">Type of the result. If not specified, it will be generated dynamically.</param>
 233        /// <param name="expression">The expression.</param>
 234        /// <param name="values">An object array that contains zero or more objects which are used as replacement values
 235        /// <returns>The generated <see cref="LambdaExpression"/></returns>
 236        [PublicAPI]
 237        public static LambdaExpression ParseLambda(bool createParameterCtor, [NotNull] ParameterExpression[] parameters,
 19238        {
 19239            return ParseLambda(null, createParameterCtor, parameters, resultType, expression, values);
 18240        }
 241    }
 242}
-
+

Methods/Properties

-ParseLambda(System.Type,System.String,System.Object[])
-ParseLambda(System.Boolean,System.Type,System.String,System.Object[])
-ParseLambda(System.Type,System.Type,System.String,System.Object[])
-ParseLambda(System.Boolean,System.Type,System.Type,System.String,System.Object[])
-ParseLambda(System.Linq.Expressions.ParameterExpression[],System.Type,System.String,System.Object[])
-ParseLambda(System.Boolean,System.Linq.Expressions.ParameterExpression[],System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Boolean,System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Boolean,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Boolean,System.Linq.Expressions.ParameterExpression[],System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Boolean,System.Linq.Expressions.ParameterExpression[],System.String,System.Object[])
+ParseLambda(System.Boolean,System.Type,System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Boolean,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Type,System.String,System.Object[])
+ParseLambda(System.Type,System.String,System.Object[])
+ParseLambda(System.Type,System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Type,System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Boolean,System.Type,System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Expressions.ParameterExpression[],System.Type,System.String,System.Object[])
+ParseLambda(System.Linq.Dynamic.Core.ParsingConfig,System.Linq.Expressions.ParameterExpression[],System.Type,System.String,System.Object[])
+ParseLambda(System.Boolean,System.Linq.Expressions.ParameterExpression[],System.Type,System.String,System.Object[])

diff --git a/report/System.Linq.Dynamic.Core_DynamicGetMemberBinder.htm b/report/System.Linq.Dynamic.Core_DynamicGetMemberBinder.htm new file mode 100644 index 00000000..57200111 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_DynamicGetMemberBinder.htm @@ -0,0 +1,87 @@ + + + + + +System.Linq.Dynamic.Core.DynamicGetMemberBinder - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.DynamicGetMemberBinder
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicGetMemberBinder.cs
Covered lines:0
Uncovered lines:11
Coverable lines:11
Total lines:34
Line coverage:0%
Branch coverage:0%
+

Metrics

+ + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.ctor(...)1000
FallbackGetMember(...)2200
.cctor()1000
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicGetMemberBinder.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1#if !NET35
 2using System.Collections.Generic;
 3using System.Dynamic;
 4using System.Linq.Expressions;
 5using System.Reflection;
 6
 7namespace System.Linq.Dynamic.Core
 8{
 9    /// <summary>
 10    /// Based on From SqlLinq by dkackman. https://github.com/dkackman/SqlLinq/blob/210b594e37f14061424397368ed750ce547c
 11    /// </summary>
 12    /// <seealso cref="GetMemberBinder" />
 13    internal class DynamicGetMemberBinder : GetMemberBinder
 14    {
 015        private static readonly PropertyInfo Indexer = typeof(IDictionary<string, object>).GetProperty("Item");
 16
 17        public DynamicGetMemberBinder(string name)
 018            : base(name, true)
 019        {
 020        }
 21
 22        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
 023        {
 024            IDictionary<string, object> dictionary = target.Value as IDictionary<string, object>;
 025             if (dictionary == null)
 026            {
 027                throw new InvalidOperationException("Target object is not an ExpandoObject");
 28            }
 29
 030            return DynamicMetaObject.Create(dictionary, Expression.MakeIndex(Expression.Constant(dictionary), Indexer, n
 031        }
 32    }
 33}
 34#endif
+
+
+ +
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_DynamicLinqTypeAttribute.htm b/report/System.Linq.Dynamic.Core_DynamicLinqTypeAttribute.htm index 9a0cff41..e8ecbdbd 100644 --- a/report/System.Linq.Dynamic.Core_DynamicLinqTypeAttribute.htm +++ b/report/System.Linq.Dynamic.Core_DynamicLinqTypeAttribute.htm @@ -25,6 +25,6 @@

Summary

File(s)

No files found. This usually happens if a file isn't covered by a test or the class does not contain any sequence points (e.g. a class that only contains auto properties).

- + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_DynamicOrdering.htm b/report/System.Linq.Dynamic.Core_DynamicOrdering.htm index e188adef..48116796 100644 --- a/report/System.Linq.Dynamic.Core_DynamicOrdering.htm +++ b/report/System.Linq.Dynamic.Core_DynamicOrdering.htm @@ -25,6 +25,6 @@

Summary

File(s)

No files found. This usually happens if a file isn't covered by a test or the class does not contain any sequence points (e.g. a class that only contains auto properties).

- + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_DynamicProperty.htm b/report/System.Linq.Dynamic.Core_DynamicProperty.htm index d1c8a2e6..c59f994e 100644 --- a/report/System.Linq.Dynamic.Core_DynamicProperty.htm +++ b/report/System.Linq.Dynamic.Core_DynamicProperty.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.DynamicProperty Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicProperty.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicProperty.cs Covered lines:7 Uncovered lines:0 Coverable lines:7 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicProperty.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicProperty.cs

@@ -47,11 +47,11 @@

- - - - - + + + + + @@ -59,7 +59,7 @@

- + @@ -67,12 +67,12 @@

- +
#LineLine coverage
 10        /// </summary>
 11        /// <param name="name">The name from the property.</param>
 12        /// <param name="type">The type from the property.</param>
 8313        public DynamicProperty(string name, Type type)
 8314        {
 8315            Name = name;
 8316            Type = type;
 8317        }
 11313        public DynamicProperty(string name, Type type)
 11314        {
 11315            Name = name;
 11316            Type = type;
 11317        }
 18
 19        /// <summary>
 20        /// Gets the name from the property.
 22        /// <value>
 23        /// The name from the property.
 24        /// </value>
 14925        public string Name { get; }
 20725        public string Name { get; }
 26
 27        /// <summary>
 28        /// Gets the type from the property.
 30        /// <value>
 31        /// The type from the property.
 32        /// </value>
 7433        public Type Type { get; }
 18433        public Type Type { get; }
 34    }
 35}
- +

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_DynamicQueryableExtensions.htm b/report/System.Linq.Dynamic.Core_DynamicQueryableExtensions.htm index 95a9eb0a..0fb5f6a7 100644 --- a/report/System.Linq.Dynamic.Core_DynamicQueryableExtensions.htm +++ b/report/System.Linq.Dynamic.Core_DynamicQueryableExtensions.htm @@ -15,13 +15,13 @@

Summary

Class:System.Linq.Dynamic.Core.DynamicQueryableExtensions Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs -Covered lines:480 -Uncovered lines:14 -Coverable lines:494 -Total lines:1375 -Line coverage:97.1% -Branch coverage:78.5% +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs +Covered lines:731 +Uncovered lines:18 +Coverable lines:749 +Total lines:2048 +Line coverage:97.5% +Branch coverage:82.3%

Metrics

@@ -29,53 +29,102 @@

Metrics

MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage   OptimizeExpression(...)348080 +Aggregate(...)22100100 Any(...)10100100 +Any(...)10100100 Any(...)10100100 +Any(...)10100100 Count(...)10100100 +Count(...)10100100 Count(...)10100100 +Count(...)10100100 +DefaultIfEmpty(...)10100100 +DefaultIfEmpty(...)10100100 Distinct(...)10100100 First(...)10100100 +First(...)10100100 First(...)10100100 +First(...)10100100 FirstOrDefault(...)10100100 +FirstOrDefault(...)10100100 FirstOrDefault(...)10100100 -GroupBy(...)10100100 +FirstOrDefault(...)10100100 +GroupBy(...)10100100 +GroupBy(...)1000 +GroupBy(...)10100100 GroupBy(...)10100100 +GroupBy(...)10100100 GroupBy(...)10100100 -GroupByMany(...)20100100 +GroupByMany(...)20100100 +GroupByMany(...)10100100 GroupByMany(...)10100100 GroupByManyInternal(...)22100100 -Join(...)73210090.91 +GroupJoin(...)10100100 +GroupJoin(...)10100100 +Join(...)10100100 +Join(...)10100100 +Join(...)1000 Join(...)1000 Last(...)10100100 +Last(...)10100100 +Last(...)10100100 +Last(...)10100100 LastOrDefault(...)10100100 +LastOrDefault(...)10100100 +LastOrDefault(...)10100100 +LastOrDefault(...)10100100 +OrderBy(...)10100100 OrderBy(...)10100100 -OrderBy(...)30100100 +OrderBy(...)30100100 +OrderBy(...)10100100 Page(...)30100100 Page(...)30100100 PageResult(...)30100100 PageResult(...)30100100 Reverse(...)10100100 +Select(...)10100100 Select(...)10100100 +Select(...)10100100 Select(...)10100100 +Select(...)10100100 Select(...)10100100 +SelectMany(...)10100100 SelectMany(...)10100100 +SelectMany(...)10100100 SelectMany(...)10100100 -SelectManyInternal(...)34100100 +SelectManyInternal(...)34100100 +SelectMany(...)10100100 SelectMany(...)10100100 +SelectMany(...)1000 SelectMany(...)10100100 +SelectMany(...)10100100 SelectMany(...)10100100 Single(...)10100100 +Single(...)10100100 +Single(...)10100100 +Single(...)10100100 SingleOrDefault(...)10100100 +SingleOrDefault(...)10100100 +SingleOrDefault(...)10100100 +SingleOrDefault(...)10100100 Skip(...)32100100 +SkipWhile(...)10100100 SkipWhile(...)10100100 Sum(...)10100100 Take(...)20100100 +TakeWhile(...)10100100 TakeWhile(...)10100100 +ThenBy(...)10100100 ThenBy(...)10100100 -ThenBy(...)30100100 +ThenBy(...)30100100 +ThenBy(...)1066.67100 +Where(...)10100100 Where(...)10100100 +Where(...)10100100 Where(...)10100100 -CreateQuery(...)2200 +Where(...)10100100 +CheckOuterAndInnerTypes(...)73210090.91 +CreateQuery(...)2210066.67 CreateQuery(...)10100100 CreateQuery(...)20100100 Execute(...)2210066.67 @@ -84,13 +133,13 @@

Metrics

Execute(...)20100100 Execute(...)10100100 Execute(...)20100100 -GetMethod(...)10100100 +GetMethod(...)1057.14100 .cctor()10100100 AsEnumerable()40100100

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs

@@ -106,1435 +155,2156 @@

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 10using System.Linq.Expressions;
 11using System.Reflection;
 12using JetBrains.Annotations;
 13#if WINDOWS_APP
 14using System;
 15using System.Linq;
 16#endif
 17
 18namespace System.Linq.Dynamic.Core
 19{
 20    /// <summary>
 21    /// Provides a set of static (Shared in Visual Basic) methods for querying data structures that implement <see cref=
 22    /// It allows dynamic string based querying. Very handy when, at compile time, you don't know the type of queries th
 23    /// or when downstream components only return column names to sort and filter by.
 24    /// </summary>
 25    public static class DynamicQueryableExtensions
 26    {
 27#if !(WINDOWS_APP45x || SILVERLIGHT)
 128        private static readonly TraceSource _ts = new TraceSource(typeof(DynamicQueryableExtensions).Name);
 29#endif
 530        private static readonly Func<MethodInfo, bool> _predicateParameterHas2 = (mi) => mi.GetParameters()[1].ToString(
 31
 32        private static Expression OptimizeExpression(Expression expression)
 42133        {
 42134             if (ExtensibilityPoint.QueryOptimizer != null)
 42035            {
 42036                var optimized = ExtensibilityPoint.QueryOptimizer(expression);
 37
 38#if !(WINDOWS_APP45x || SILVERLIGHT)
 42039                 if (optimized != expression)
 040                {
 41                    _ts.TraceEvent(TraceEventType.Verbose, 0, "Expression before : {0}", expression);
 42                    _ts.TraceEvent(TraceEventType.Verbose, 0, "Expression after  : {0}", optimized);
 043                }
 44#endif
 42045                return optimized;
 46            }
 47
 148            return expression;
 42149        }
 50
 51        #region Any
 152        private static readonly MethodInfo _any = GetMethod(nameof(Queryable.Any));
 53
 54        /// <summary>
 55        /// Determines whether a sequence contains any elements.
 56        /// </summary>
 57        /// <param name="source">A sequence to check for being empty.</param>
 58        /// <example>
 59        /// <code language="cs">
 60        /// IQueryable queryable = employees.AsQueryable();
 61        /// var result = queryable.Any();
 62        /// </code>
 63        /// </example>
 64        /// <returns>true if the source sequence contains any elements; otherwise, false.</returns>
 65        public static bool Any([NotNull] this IQueryable source)
 1066        {
 1067            Check.NotNull(source, nameof(source));
 68
 1069            return Execute<bool>(_any, source);
 1070        }
 71
 172        private static readonly MethodInfo _anyPredicate = GetMethod(nameof(Queryable.Any), 1);
 73
 74        /// <summary>
 75        /// Determines whether a sequence contains any elements.
 76        /// </summary>
 77        /// <param name="source">A sequence to check for being empty.</param>
 78        /// <param name="predicate">A function to test each element for a condition.</param>
 79        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 80        /// <example>
 81        /// <code language="cs">
 82        /// IQueryable queryable = employees.AsQueryable();
 83        /// var result1 = queryable.Any("Income > 50");
 84        /// var result2 = queryable.Any("Income > @0", 50);
 85        /// var result3 = queryable.Select("Roles.Any()");
 86        /// </code>
 87        /// </example>
 88        /// <returns>true if the source sequence contains any elements; otherwise, false.</returns>
 89        public static bool Any([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 490        {
 491            Check.NotNull(source, nameof(source));
 492            Check.NotEmpty(predicate, nameof(predicate));
 93
 494            bool createParameterCtor = source.IsLinqToObjects();
 495            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 96
 497            return Execute<bool>(_anyPredicate, source, lambda);
 498        }
 99        #endregion Any
 100
 101        #region AsEnumerable
 102#if NET35
 103        /// <summary>
 104        /// Returns the input typed as <see cref="IEnumerable{T}"/> of <see cref="object"/>./>
 105        /// </summary>
 106        /// <param name="source">The sequence to type as <see cref="IEnumerable{T}"/> of <see cref="object"/>.</param>
 107        /// <returns>The input typed as <see cref="IEnumerable{T}"/> of <see cref="object"/>.</returns>
 108        public static IEnumerable<object> AsEnumerable([NotNull] this IQueryable source)
 109#else
 110        /// <summary>
 111        /// Returns the input typed as <see cref="IEnumerable{T}"/> of dynamic.
 112        /// </summary>
 113        /// <param name="source">The sequence to type as <see cref="IEnumerable{T}"/> of dynamic.</param>
 114        /// <returns>The input typed as <see cref="IEnumerable{T}"/> of dynamic.</returns>
 115        public static IEnumerable<dynamic> AsEnumerable([NotNull] this IQueryable source)
 116#endif
 5117        {
 419118            foreach (var obj in source)
 202119            {
 202120                yield return obj;
 202121            }
 5122        }
 123        #endregion AsEnumerable
 13using System.Linq.Dynamic.Core.Parser;
 14
 15#if WINDOWS_APP
 16using System;
 17using System.Linq;
 18#endif
 19
 20namespace System.Linq.Dynamic.Core
 21{
 22    /// <summary>
 23    /// Provides a set of static (Shared in Visual Basic) methods for querying data structures that implement <see cref=
 24    /// It allows dynamic string based querying. Very handy when, at compile time, you don't know the type of queries th
 25    /// or when downstream components only return column names to sort and filter by.
 26    /// </summary>
 27    public static class DynamicQueryableExtensions
 28    {
 29#if !(WINDOWS_APP45x || SILVERLIGHT)
 130        private static readonly TraceSource TraceSource = new TraceSource(typeof(DynamicQueryableExtensions).Name);
 31#endif
 32
 33        private static Expression OptimizeExpression(Expression expression)
 53334        {
 53335             if (ExtensibilityPoint.QueryOptimizer != null)
 53236            {
 53237                var optimized = ExtensibilityPoint.QueryOptimizer(expression);
 38
 39#if !(WINDOWS_APP45x || SILVERLIGHT)
 53240                 if (optimized != expression)
 041                {
 42                    TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Expression before : {0}", expression);
 43                    TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Expression after  : {0}", optimized);
 044                }
 45#endif
 53246                return optimized;
 47            }
 48
 149            return expression;
 53350        }
 51
 52        #region Aggregate
 53        /// <summary>
 54        /// Dynamically runs an aggregate function on the IQueryable.
 55        /// </summary>
 56        /// <param name="source">The IQueryable data source.</param>
 57        /// <param name="function">The name of the function to run. Can be Sum, Average, Min or Max.</param>
 58        /// <param name="member">The name of the property to aggregate over.</param>
 59        /// <returns>The value of the aggregate function run over the specified property.</returns>
 60        public static object Aggregate([NotNull] this IQueryable source, [NotNull] string function, [NotNull] string mem
 1261        {
 1262            Check.NotNull(source, nameof(source));
 1263            Check.NotEmpty(function, nameof(function));
 1264            Check.NotEmpty(member, nameof(member));
 65
 66            // Properties
 1267            PropertyInfo property = source.ElementType.GetProperty(member);
 1268            ParameterExpression parameter = ParameterExpressionHelper.CreateParameterExpression(source.ElementType, "s")
 1269            Expression selector = Expression.Lambda(Expression.MakeMemberAccess(parameter, property), parameter);
 70            // We've tried to find an expression of the type Expression<Func<TSource, TAcc>>,
 71            // which is expressed as ( (TSource s) => s.Price );
 72
 229873             var methods = typeof(Queryable).GetMethods().Where(x => x.Name == function && x.IsGenericMethod);
 74
 75            // Method
 1276            MethodInfo aggregateMethod = methods.SingleOrDefault(m =>
 8477            {
 8478                ParameterInfo lastParameter = m.GetParameters().LastOrDefault();
 1279
 8480                 return lastParameter != null ? TypeHelper.GetUnderlyingType(lastParameter.ParameterType) == property.Pro
 8481            });
 82
 83            // Sum, Average
 1284             if (aggregateMethod != null)
 685            {
 686                return source.Provider.Execute(
 687                    Expression.Call(
 688                        null,
 689                        aggregateMethod.MakeGenericMethod(source.ElementType),
 690                        new[] { source.Expression, Expression.Quote(selector) }));
 91            }
 92
 93            // Min, Max
 1894            aggregateMethod = methods.SingleOrDefault(m => m.Name == function && m.GetGenericArguments().Length == 2);
 95
 696            return source.Provider.Execute(
 697                Expression.Call(
 698                    null,
 699                    aggregateMethod.MakeGenericMethod(source.ElementType, property.PropertyType),
 6100                    new[] { source.Expression, Expression.Quote(selector) }));
 12101        }
 102        #endregion Aggregate
 103
 104        #region Any
 1105        private static readonly MethodInfo _any = GetMethod(nameof(Queryable.Any));
 106
 107        /// <summary>
 108        /// Determines whether a sequence contains any elements.
 109        /// </summary>
 110        /// <param name="source">A sequence to check for being empty.</param>
 111        /// <example>
 112        /// <code language="cs">
 113        /// IQueryable queryable = employees.AsQueryable();
 114        /// var result = queryable.Any();
 115        /// </code>
 116        /// </example>
 117        /// <returns>true if the source sequence contains any elements; otherwise, false.</returns>
 118        public static bool Any([NotNull] this IQueryable source)
 10119        {
 10120            Check.NotNull(source, nameof(source));
 121
 10122            return Execute<bool>(_any, source);
 10123        }
 124
 125        #region Count
 1126        private static readonly MethodInfo _count = GetMethod(nameof(Queryable.Count));
 127
 128        /// <summary>
 129        /// Returns the number of elements in a sequence.
 130        /// </summary>
 131        /// <param name="source">The <see cref="IQueryable"/> that contains the elements to be counted.</param>
 132        /// <example>
 133        /// <code language="cs">
 134        /// IQueryable queryable = employees.AsQueryable();
 135        /// var result = queryable.Count();
 136        /// </code>
 137        /// </example>
 138        /// <returns>The number of elements in the input sequence.</returns>
 139        public static int Count([NotNull] this IQueryable source)
 32140        {
 32141            Check.NotNull(source, nameof(source));
 142
 32143            return Execute<int>(_count, source);
 32144        }
 145
 1146        private static readonly MethodInfo _countPredicate = GetMethod(nameof(Queryable.Count), 1);
 147
 148        /// <summary>
 149        /// Returns the number of elements in a sequence.
 150        /// </summary>
 151        /// <param name="source">The <see cref="IQueryable"/> that contains the elements to be counted.</param>
 152        /// <param name="predicate">A function to test each element for a condition.</param>
 153        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 154        /// <example>
 155        /// <code language="cs">
 156        /// IQueryable queryable = employees.AsQueryable();
 157        /// var result1 = queryable.Count("Income > 50");
 158        /// var result2 = queryable.Count("Income > @0", 50);
 159        /// var result3 = queryable.Select("Roles.Count()");
 160        /// </code>
 161        /// </example>
 162        /// <returns>The number of elements in the specified sequence that satisfies a condition.</returns>
 163        public static int Count([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 3164        {
 3165            Check.NotNull(source, nameof(source));
 3166            Check.NotEmpty(predicate, nameof(predicate));
 167
 3168            bool createParameterCtor = source.IsLinqToObjects();
 3169            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 170
 3171            return Execute<int>(_countPredicate, source, lambda);
 3172        }
 173        #endregion Count
 174
 175        #region Distinct
 1176        private static readonly MethodInfo _distinct = GetMethod(nameof(Queryable.Distinct));
 177
 1125        private static readonly MethodInfo _anyPredicate = GetMethod(nameof(Queryable.Any), 1);
 126
 127        /// <summary>
 128        /// Determines whether a sequence contains any elements.
 129        /// </summary>
 130        /// <param name="source">A sequence to check for being empty.</param>
 131        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 132        /// <param name="predicate">A function to test each element for a condition.</param>
 133        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 134        /// <example>
 135        /// <code language="cs">
 136        /// IQueryable queryable = employees.AsQueryable();
 137        /// var result1 = queryable.Any("Income > 50");
 138        /// var result2 = queryable.Any("Income > @0", 50);
 139        /// var result3 = queryable.Select("Roles.Any()");
 140        /// </code>
 141        /// </example>
 142        /// <returns>true if the source sequence contains any elements; otherwise, false.</returns>
 143        [PublicAPI]
 144        public static bool Any([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string pred
 5145        {
 5146            Check.NotNull(source, nameof(source));
 5147            Check.NotEmpty(predicate, nameof(predicate));
 148
 5149            bool createParameterCtor = source.IsLinqToObjects();
 5150            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 151
 5152            return Execute<bool>(_anyPredicate, source, lambda);
 5153        }
 154
 155        /// <inheritdoc cref="Any(IQueryable, ParsingConfig, string, object[])"/>
 156        public static bool Any([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 4157        {
 4158            return Any(source, null, predicate, args);
 4159        }
 160
 161        /// <summary>
 162        /// Determines whether a sequence contains any elements.
 163        /// </summary>
 164        /// <param name="source">A sequence to check for being empty.</param>
 165        /// <param name="lambda">A cached Lambda Expression.</param>
 166        /// <returns>true if the source sequence contains any elements; otherwise, false.</returns>
 167        public static bool Any([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 1168        {
 1169            Check.NotNull(source, nameof(source));
 1170            Check.NotNull(lambda, nameof(lambda));
 171
 1172            return Execute<bool>(_anyPredicate, source, lambda);
 1173        }
 174        #endregion Any
 175
 176        #region AsEnumerable
 177#if NET35
 178        /// <summary>
 179        /// Returns distinct elements from a sequence by using the default equality comparer to compare values.
 179        /// Returns the input typed as <see cref="IEnumerable{T}"/> of <see cref="object"/>./>
 180        /// </summary>
 181        /// <param name="source">The sequence to remove duplicate elements from.</param>
 182        /// <example>
 183        /// <code language="cs">
 184        /// IQueryable queryable = employees.AsQueryable();
 185        /// var result1 = queryable.Distinct();
 186        /// var result2 = queryable.Select("Roles.Distinct()");
 187        /// </code>
 188        /// </example>
 189        /// <returns>An <see cref="IQueryable"/> that contains distinct elements from the source sequence.</returns>
 190        public static IQueryable Distinct([NotNull] this IQueryable source)
 2191        {
 2192            Check.NotNull(source, nameof(source));
 193
 2194            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "Distinct", new Type[] { source.Elemen
 2195            return source.Provider.CreateQuery(optimized);
 2196        }
 197        #endregion Distinct
 198
 199        #region First
 1200        private static readonly MethodInfo _first = GetMethod(nameof(Queryable.First));
 201
 202        /// <summary>
 203        /// Returns the first element of a sequence.
 204        /// </summary>
 205        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 206        /// <returns>The first element in source.</returns>
 207#if NET35
 208        public static object First([NotNull] this IQueryable source)
 209#else
 210        public static dynamic First([NotNull] this IQueryable source)
 211#endif
 7212        {
 7213            Check.NotNull(source, nameof(source));
 214
 7215            return Execute(_first, source);
 7216        }
 181        /// <param name="source">The sequence to type as <see cref="IEnumerable{T}"/> of <see cref="object"/>.</param>
 182        /// <returns>The input typed as <see cref="IEnumerable{T}"/> of <see cref="object"/>.</returns>
 183        public static IEnumerable<object> AsEnumerable([NotNull] this IQueryable source)
 184#else
 185        /// <summary>
 186        /// Returns the input typed as <see cref="IEnumerable{T}"/> of dynamic.
 187        /// </summary>
 188        /// <param name="source">The sequence to type as <see cref="IEnumerable{T}"/> of dynamic.</param>
 189        /// <returns>The input typed as <see cref="IEnumerable{T}"/> of dynamic.</returns>
 190        public static IEnumerable<dynamic> AsEnumerable([NotNull] this IQueryable source)
 191#endif
 5192        {
 419193            foreach (var obj in source)
 202194            {
 202195                yield return obj;
 202196            }
 5197        }
 198        #endregion AsEnumerable
 199
 200        #region Count
 1201        private static readonly MethodInfo _count = GetMethod(nameof(Queryable.Count));
 202
 203        /// <summary>
 204        /// Returns the number of elements in a sequence.
 205        /// </summary>
 206        /// <param name="source">The <see cref="IQueryable"/> that contains the elements to be counted.</param>
 207        /// <example>
 208        /// <code language="cs">
 209        /// IQueryable queryable = employees.AsQueryable();
 210        /// var result = queryable.Count();
 211        /// </code>
 212        /// </example>
 213        /// <returns>The number of elements in the input sequence.</returns>
 214        public static int Count([NotNull] this IQueryable source)
 33215        {
 33216            Check.NotNull(source, nameof(source));
 217
 1218        private static readonly MethodInfo _firstPredicate = GetMethod(nameof(Queryable.First), 1);
 219
 220        /// <summary>
 221        /// Returns the first element of a sequence that satisfies a specified condition.
 222        /// </summary>
 223        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 224        /// <param name="predicate">A function to test each element for a condition.</param>
 225        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 226        /// <returns>The first element in source that passes the test in predicate.</returns>
 227#if NET35
 228        public static object First([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 229#else
 230        public static dynamic First([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 231#endif
 2232        {
 2233            Check.NotNull(source, nameof(source));
 2234            Check.NotEmpty(predicate, nameof(predicate));
 235
 2236            bool createParameterCtor = source.IsLinqToObjects();
 2237            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 238
 2239            return Execute(_firstPredicate, source, lambda);
 2240        }
 241        #endregion First
 242
 243        #region FirstOrDefault
 244        /// <summary>
 245        /// Returns the first element of a sequence, or a default value if the sequence contains no elements.
 246        /// </summary>
 247        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 248        /// <returns>default if source is empty; otherwise, the first element in source.</returns>
 249#if NET35
 250        public static object FirstOrDefault([NotNull] this IQueryable source)
 251#else
 252        public static dynamic FirstOrDefault([NotNull] this IQueryable source)
 253#endif
 9254        {
 9255            Check.NotNull(source, nameof(source));
 33218            return Execute<int>(_count, source);
 33219        }
 220
 1221        private static readonly MethodInfo _countPredicate = GetMethod(nameof(Queryable.Count), 1);
 222
 223        /// <summary>
 224        /// Returns the number of elements in a sequence.
 225        /// </summary>
 226        /// <param name="source">The <see cref="IQueryable"/> that contains the elements to be counted.</param>
 227        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 228        /// <param name="predicate">A function to test each element for a condition.</param>
 229        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 230        /// <example>
 231        /// <code language="cs">
 232        /// IQueryable queryable = employees.AsQueryable();
 233        /// var result1 = queryable.Count("Income > 50");
 234        /// var result2 = queryable.Count("Income > @0", 50);
 235        /// var result3 = queryable.Select("Roles.Count()");
 236        /// </code>
 237        /// </example>
 238        /// <returns>The number of elements in the specified sequence that satisfies a condition.</returns>
 239        [PublicAPI]
 240        public static int Count([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string pre
 3241        {
 3242            Check.NotNull(source, nameof(source));
 3243            Check.NotEmpty(predicate, nameof(predicate));
 244
 3245            bool createParameterCtor = source.IsLinqToObjects();
 3246            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 247
 3248            return Execute<int>(_countPredicate, source, lambda);
 3249        }
 250
 251        /// <inheritdoc cref="Count(IQueryable, ParsingConfig, string, object[])"/>
 252        public static int Count([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 3253        {
 3254            return Count(source, null, predicate, args);
 3255        }
 256
 9257            return Execute(_firstOrDefault, source);
 9258        }
 1259        private static readonly MethodInfo _firstOrDefault = GetMethod(nameof(Queryable.FirstOrDefault));
 260
 261        /// <summary>
 262        /// Returns the first element of a sequence that satisfies a specified condition or a default value if no such e
 263        /// </summary>
 264        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 265        /// <param name="predicate">A function to test each element for a condition.</param>
 266        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 267        /// <returns>default if source is empty or if no element passes the test specified by predicate; otherwise, the 
 268#if NET35
 269        public static object FirstOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[
 270#else
 271        public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object
 272#endif
 2273        {
 2274            Check.NotNull(source, nameof(source));
 2275            Check.NotEmpty(predicate, nameof(predicate));
 276
 2277            bool createParameterCtor = source.IsLinqToObjects();
 2278            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 279
 2280            return Execute(_firstOrDefaultPredicate, source, lambda);
 2281        }
 1282        private static readonly MethodInfo _firstOrDefaultPredicate = GetMethod(nameof(Queryable.FirstOrDefault), 1);
 283        #endregion FirstOrDefault
 284
 285        #region GroupBy
 286        /// <summary>
 287        /// Groups the elements of a sequence according to a specified key string function
 288        /// and creates a result value from each group and its key.
 289        /// </summary>
 290        /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param>
 291        /// <param name="keySelector">A string expression to specify the key for each element.</param>
 292        /// <param name="resultSelector">A string expression to specify a result value from each group.</param>
 293        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 294        /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</re
 295        /// <example>
 296        /// <code>
 297        /// var groupResult1 = queryable.GroupBy("NumberPropertyAsKey", "StringProperty");
 298        /// var groupResult2 = queryable.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)", "new (StringProperty1
 299        /// </code>
 300        /// </example>
 301        public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [NotNull] strin
 5302        {
 5303            Check.NotNull(source, nameof(source));
 5304            Check.NotEmpty(keySelector, nameof(keySelector));
 5305            Check.NotEmpty(resultSelector, nameof(resultSelector));
 306
 5307            bool createParameterCtor = source.IsLinqToObjects();
 5308            LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, nu
 5309            LambdaExpression elementLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType
 310
 5311            var optimized = OptimizeExpression(Expression.Call(
 5312                typeof(Queryable), "GroupBy",
 5313                new[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
 5314                source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));
 315
 5316            return source.Provider.CreateQuery(optimized);
 5317        }
 318
 319        /// <summary>
 320        /// Groups the elements of a sequence according to a specified key string function
 321        /// and creates a result value from each group and its key.
 322        /// </summary>
 323        /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param>
 324        /// <param name="keySelector">A string expression to specify the key for each element.</param>
 325        /// <param name="resultSelector">A string expression to specify a result value from each group.</param>
 326        /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</re
 327        /// <example>
 328        /// <code>
 329        /// var groupResult1 = queryable.GroupBy("NumberPropertyAsKey", "StringProperty");
 330        /// var groupResult2 = queryable.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)", "new (StringProperty1
 331        /// </code>
 332        /// </example>
 333        public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [NotNull] strin
 8334        {
 8335            Check.NotNull(source, nameof(source));
 8336            Check.NotEmpty(keySelector, nameof(keySelector));
 8337            Check.NotEmpty(resultSelector, nameof(resultSelector));
 338
 5339            return GroupBy(source, keySelector, resultSelector, null);
 5340        }
 341
 342        /// <summary>
 343        /// Groups the elements of a sequence according to a specified key string function
 344        /// and creates a result value from each group and its key.
 345        /// </summary>
 346        /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param>
 347        /// <param name="keySelector">A string expression to specify the key for each element.</param>
 348        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 349        /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</re
 350        /// <example>
 351        /// <code>
 352        /// var groupResult1 = queryable.GroupBy("NumberPropertyAsKey");
 353        /// var groupResult2 = queryable.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)");
 354        /// </code>
 355        /// </example>
 356        public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [CanBeNull] par
 17357        {
 17358            Check.NotNull(source, nameof(source));
 16359            Check.NotEmpty(keySelector, nameof(keySelector));
 360
 13361            bool createParameterCtor = source.IsLinqToObjects();
 13362            LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, nu
 363
 8364            var optimized = OptimizeExpression(Expression.Call(
 8365                typeof(Queryable), nameof(Queryable.GroupBy),
 8366                new[] { source.ElementType, keyLambda.Body.Type },
 8367                new[] { source.Expression, Expression.Quote(keyLambda) }));
 368
 8369            return source.Provider.CreateQuery(optimized);
 8370        }
 371        #endregion GroupBy
 372
 373        #region GroupByMany
 374        /// <summary>
 375        /// Groups the elements of a sequence according to multiple specified key string functions
 376        /// and creates a result value from each group (and subgroups) and its key.
 377        /// </summary>
 378        /// <typeparam name="TElement"></typeparam>
 379        /// <param name="source">A <see cref="IEnumerable{T}"/> whose elements to group.</param>
 380        /// <param name="keySelectors"><see cref="string"/> expressions to specify the keys for each element.</param>
 381        /// <returns>A <see cref="IEnumerable{T}"/> of type <see cref="GroupResult"/> where each element represents a pr
 382        public static IEnumerable<GroupResult> GroupByMany<TElement>([NotNull] this IEnumerable<TElement> source, params
 1383        {
 1384            Check.NotNull(source, nameof(source));
 1385            Check.HasNoNulls(keySelectors, nameof(keySelectors));
 386
 1387            var selectors = new List<Func<TElement, object>>(keySelectors.Length);
 388
 1389            bool createParameterCtor = true;
 7390            foreach (var selector in keySelectors)
 2391            {
 2392                LambdaExpression l = DynamicExpressionParser.ParseLambda(createParameterCtor, typeof(TElement), typeof(o
 2393                selectors.Add((Func<TElement, object>)l.Compile());
 2394            }
 395
 1396            return GroupByManyInternal(source, selectors.ToArray(), 0);
 1397        }
 398
 399        /// <summary>
 400        /// Groups the elements of a sequence according to multiple specified key functions
 401        /// and creates a result value from each group (and subgroups) and its key.
 402        /// </summary>
 403        /// <typeparam name="TElement"></typeparam>
 404        /// <param name="source">A <see cref="IEnumerable{T}"/> whose elements to group.</param>
 405        /// <param name="keySelectors">Lambda expressions to specify the keys for each element.</param>
 406        /// <returns>A <see cref="IEnumerable{T}"/> of type <see cref="GroupResult"/> where each element represents a pr
 407        public static IEnumerable<GroupResult> GroupByMany<TElement>([NotNull] this IEnumerable<TElement> source, params
 1408        {
 1409            Check.NotNull(source, nameof(source));
 1410            Check.HasNoNulls(keySelectors, nameof(keySelectors));
 411
 1412            return GroupByManyInternal(source, keySelectors, 0);
 1413        }
 414
 415        static IEnumerable<GroupResult> GroupByManyInternal<TElement>(IEnumerable<TElement> source, Func<TElement, objec
 15416        {
 21417             if (currentSelector >= keySelectors.Length) return null;
 418
 9419            var selector = keySelectors[currentSelector];
 420
 9421            var result = source.GroupBy(selector).Select(
 22422                g => new GroupResult
 22423                {
 22424                    Key = g.Key,
 22425                    Count = g.Count(),
 22426                    Items = g,
 22427                    Subgroups = GroupByManyInternal(g, keySelectors, currentSelector + 1)
 22428                });
 429
 9430            return result;
 15431        }
 432        #endregion GroupByMany
 433
 434        #region Join
 435        /// <summary>
 436        /// Correlates the elements of two sequences based on matching keys. The default equality comparer is used to co
 437        /// </summary>
 438        /// <param name="outer">The first sequence to join.</param>
 439        /// <param name="inner">The sequence to join to the first sequence.</param>
 440        /// <param name="outerKeySelector">A dynamic function to extract the join key from each element of the first seq
 441        /// <param name="innerKeySelector">A dynamic function to extract the join key from each element of the second se
 442        /// <param name="resultSelector">A dynamic function to create a result element from two matching elements.</para
 443        /// <param name="args">An object array that contains zero or more objects to insert into the predicates as param
 444        /// <returns>An <see cref="IQueryable"/> obtained by performing an inner join on two sequences.</returns>
 445        public static IQueryable Join([NotNull] this IQueryable outer, [NotNull] IEnumerable inner, [NotNull] string out
 4446        {
 447            //http://stackoverflow.com/questions/389094/how-to-create-a-dynamic-linq-join-extension-method
 448
 4449            Check.NotNull(outer, nameof(outer));
 4450            Check.NotNull(inner, nameof(inner));
 4451            Check.NotEmpty(outerKeySelector, nameof(outerKeySelector));
 4452            Check.NotEmpty(innerKeySelector, nameof(innerKeySelector));
 4453            Check.NotEmpty(resultSelector, nameof(resultSelector));
 454
 4455            Type outerType = outer.ElementType;
 4456            Type innerType = inner.AsQueryable().ElementType;
 457
 4458            bool createParameterCtor = outer.IsLinqToObjects();
 4459            LambdaExpression outerSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, outerType, n
 4460            LambdaExpression innerSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, innerType, n
 461
 4462            Type outerSelectorReturnType = outerSelectorLambda.Body.Type;
 4463            Type innerSelectorReturnType = innerSelectorLambda.Body.Type;
 464
 465            // If types are not the same, try to convert to Nullable and generate new LambdaExpression
 4466             if (outerSelectorReturnType != innerSelectorReturnType)
 3467            {
 3468                 if (ExpressionParser.IsNullableType(outerSelectorReturnType) && !ExpressionParser.IsNullableType(innerSe
 1469                {
 1470                    innerSelectorReturnType = ExpressionParser.ToNullableType(innerSelectorReturnType);
 1471                    innerSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, innerType, innerSelec
 1472                }
 2473                 else if (!ExpressionParser.IsNullableType(outerSelectorReturnType) && ExpressionParser.IsNullableType(in
 1474                {
 1475                    outerSelectorReturnType = ExpressionParser.ToNullableType(outerSelectorReturnType);
 1476                    outerSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, outerType, outerSelec
 1477                }
 257        /// <summary>
 258        /// Returns the number of elements in a sequence.
 259        /// </summary>
 260        /// <param name="source">The <see cref="IQueryable"/> that contains the elements to be counted.</param>
 261        /// <param name="lambda">A cached Lambda Expression.</param>
 262        /// <returns>The number of elements in the specified sequence that satisfies a condition.</returns>
 263        public static int Count([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 1264        {
 1265            Check.NotNull(source, nameof(source));
 1266            Check.NotNull(lambda, nameof(lambda));
 267
 1268            return Execute<int>(_countPredicate, source, lambda);
 1269        }
 270        #endregion Count
 271
 272        #region DefaultIfEmpty
 1273        private static readonly MethodInfo _defaultIfEmpty = GetMethod(nameof(Queryable.DefaultIfEmpty));
 1274        private static readonly MethodInfo _defaultIfEmptyWithParam = GetMethod(nameof(Queryable.DefaultIfEmpty), 1);
 275
 276        /// <summary>
 277        /// Returns the elements of the specified sequence or the type parameter's default value in a singleton collecti
 278        /// </summary>
 279        /// <param name="source">The <see cref="IQueryable"/> to return a default value for if empty.</param>
 280        /// <example>
 281        /// <code language="cs">
 282        /// IQueryable queryable = employees.DefaultIfEmpty();
 283        /// </code>
 284        /// </example>
 285        /// <returns>An <see cref="IQueryable"/> that contains default if source is empty; otherwise, source.</returns>
 286        public static IQueryable DefaultIfEmpty([NotNull] this IQueryable source)
 4287        {
 4288            Check.NotNull(source, nameof(source));
 289
 4290            return CreateQuery(_defaultIfEmpty, source);
 4291        }
 292
 293        /// <summary>
 294        /// Returns the elements of the specified sequence or the type parameter's default value in a singleton collecti
 295        /// </summary>
 296        /// <param name="source">The <see cref="IQueryable"/> to return a default value for if empty.</param>
 297        /// <param name="defaultValue">The value to return if the sequence is empty.</param>
 298        /// <example>
 299        /// <code language="cs">
 300        /// IQueryable queryable = employees.DefaultIfEmpty(new Employee());
 301        /// </code>
 302        /// </example>
 303        /// <returns>An <see cref="IQueryable"/> that contains defaultValue if source is empty; otherwise, source.</retu
 304        public static IQueryable DefaultIfEmpty([NotNull] this IQueryable source, [CanBeNull] object defaultValue)
 4305        {
 4306            Check.NotNull(source, nameof(source));
 307
 4308            return CreateQuery(_defaultIfEmptyWithParam, source, Expression.Constant(defaultValue));
 4309        }
 310        #endregion
 311
 312        #region Distinct
 1313        private static readonly MethodInfo _distinct = GetMethod(nameof(Queryable.Distinct));
 314
 315        /// <summary>
 316        /// Returns distinct elements from a sequence by using the default equality comparer to compare values.
 317        /// </summary>
 318        /// <param name="source">The sequence to remove duplicate elements from.</param>
 319        /// <example>
 320        /// <code language="cs">
 321        /// IQueryable queryable = employees.AsQueryable();
 322        /// var result1 = queryable.Distinct();
 323        /// var result2 = queryable.Select("Roles.Distinct()");
 324        /// </code>
 325        /// </example>
 326        /// <returns>An <see cref="IQueryable"/> that contains distinct elements from the source sequence.</returns>
 327        public static IQueryable Distinct([NotNull] this IQueryable source)
 2328        {
 2329            Check.NotNull(source, nameof(source));
 330
 2331            return CreateQuery(_distinct, source);
 2332        }
 333        #endregion Distinct
 334
 335        #region First
 1336        private static readonly MethodInfo _first = GetMethod(nameof(Queryable.First));
 337
 338        /// <summary>
 339        /// Returns the first element of a sequence.
 340        /// </summary>
 341        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 342        /// <returns>The first element in source.</returns>
 343#if NET35
 344        public static object First([NotNull] this IQueryable source)
 345#else
 346        public static dynamic First([NotNull] this IQueryable source)
 347#endif
 14348        {
 14349            Check.NotNull(source, nameof(source));
 350
 14351            return Execute(_first, source);
 14352        }
 353
 1354        private static readonly MethodInfo _firstPredicate = GetMethod(nameof(Queryable.First), 1);
 355
 356        /// <summary>
 357        /// Returns the first element of a sequence that satisfies a specified condition.
 358        /// </summary>
 359        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 360        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 361        /// <param name="predicate">A function to test each element for a condition.</param>
 362        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 363        /// <returns>The first element in source that passes the test in predicate.</returns>
 364        [PublicAPI]
 365#if NET35
 366        public static object First([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string 
 367#else
 368        public static dynamic First([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string
 369#endif
 5370        {
 5371            Check.NotNull(source, nameof(source));
 5372            Check.NotEmpty(predicate, nameof(predicate));
 373
 5374            bool createParameterCtor = source.IsLinqToObjects();
 5375            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 376
 5377            return Execute(_firstPredicate, source, lambda);
 5378        }
 379
 380        /// <inheritdoc cref="First(IQueryable, ParsingConfig, string, object[])"/>
 381#if NET35
 382        public static object First([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 383#else
 384        public static dynamic First([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 385#endif
 4386        {
 4387            return First(source, null, predicate, args);
 4388        }
 389
 390        /// <summary>
 391        /// Returns the first element of a sequence that satisfies a specified condition.
 392        /// </summary>
 393        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 394        /// <param name="lambda">A cached Lambda Expression.</param>
 395        /// <returns>The first element in source that passes the test in predicate.</returns>
 396#if NET35
 397        public static object First([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 398#else
 399        public static dynamic First([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 400#endif
 1401        {
 1402            Check.NotNull(source, nameof(source));
 1403            return Execute(_firstPredicate, source, lambda);
 1404        }
 405        #endregion First
 406
 407        #region FirstOrDefault
 1408        private static readonly MethodInfo _firstOrDefault = GetMethod(nameof(Queryable.FirstOrDefault));
 409
 410        /// <summary>
 411        /// Returns the first element of a sequence, or a default value if the sequence contains no elements.
 412        /// </summary>
 413        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 414        /// <returns>default if source is empty; otherwise, the first element in source.</returns>
 415#if NET35
 416        public static object FirstOrDefault([NotNull] this IQueryable source)
 417#else
 418        public static dynamic FirstOrDefault([NotNull] this IQueryable source)
 419#endif
 12420        {
 12421            Check.NotNull(source, nameof(source));
 422
 12423            return Execute(_firstOrDefault, source);
 12424        }
 425
 426        /// <summary>
 427        /// Returns the first element of a sequence that satisfies a specified condition or a default value if no such e
 428        /// </summary>
 429        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 430        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 431        /// <param name="predicate">A function to test each element for a condition.</param>
 432        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 433        /// <returns>default if source is empty or if no element passes the test specified by predicate; otherwise, the 
 434        [PublicAPI]
 435#if NET35
 436        public static object FirstOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull
 437#else
 438        public static dynamic FirstOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNul
 439#endif
 39440        {
 39441            Check.NotNull(source, nameof(source));
 39442            Check.NotEmpty(predicate, nameof(predicate));
 443
 39444            bool createParameterCtor = source.IsLinqToObjects();
 39445            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 446
 39447            return Execute(_firstOrDefaultPredicate, source, lambda);
 39448        }
 449
 450        /// <inheritdoc cref="FirstOrDefault(IQueryable, ParsingConfig, string, object[])"/>
 451#if NET35
 452        public static object FirstOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[
 453#else
 454        public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object
 455#endif
 38456        {
 38457            return FirstOrDefault(source, null, predicate, args);
 38458        }
 459
 460        /// <summary>
 461        /// Returns the first element of a sequence that satisfies a specified condition or a default value if no such e
 462        /// </summary>
 463        /// <param name="source">The <see cref="IQueryable"/> to return the first element of.</param>
 464        /// <param name="lambda">A cached Lambda Expression.</param>
 465        /// <returns>default if source is empty or if no element passes the test specified by predicate; otherwise, the 
 466#if NET35
 467        public static object FirstOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 468#else
 469        public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 470#endif
 1471        {
 1472            Check.NotNull(source, nameof(source));
 473
 1474            return Execute(_firstOrDefaultPredicate, source, lambda);
 1475        }
 1476        private static readonly MethodInfo _firstOrDefaultPredicate = GetMethod(nameof(Queryable.FirstOrDefault), 1);
 477        #endregion FirstOrDefault
 478
 479                // If types are still not the same, throw an Exception
 3480                 if (outerSelectorReturnType != innerSelectorReturnType)
 1481                {
 1482                    throw new ParseException(string.Format(CultureInfo.CurrentCulture, Res.IncompatibleTypes, outerType,
 483                }
 2484            }
 485
 3486            ParameterExpression[] parameters =
 3487            {
 3488                Expression.Parameter(outerType, "outer"), Expression.Parameter(innerType, "inner")
 3489            };
 490
 3491            LambdaExpression resultSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, parameters,
 492
 3493            var optimized = OptimizeExpression(Expression.Call(
 3494                typeof(Queryable), "Join",
 3495                new[] { outerType, innerType, outerSelectorLambda.Body.Type, resultSelectorLambda.Body.Type },
 3496                outer.Expression, // outer: The first sequence to join.
 3497                inner.AsQueryable().Expression, // inner: The sequence to join to the first sequence.
 3498                Expression.Quote(outerSelectorLambda), // outerKeySelector: A function to extract the join key from each
 3499                Expression.Quote(innerSelectorLambda), // innerKeySelector: A function to extract the join key from each
 3500                Expression.Quote(resultSelectorLambda) // resultSelector: A function to create a result element from two
 3501            ));
 479        #region GroupBy
 480        /// <summary>
 481        /// Groups the elements of a sequence according to a specified key string function
 482        /// and creates a result value from each group and its key.
 483        /// </summary>
 484        /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param>
 485        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 486        /// <param name="keySelector">A string expression to specify the key for each element.</param>
 487        /// <param name="resultSelector">A string expression to specify a result value from each group.</param>
 488        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 489        /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</re
 490        /// <example>
 491        /// <code>
 492        /// var groupResult1 = queryable.GroupBy("NumberPropertyAsKey", "StringProperty");
 493        /// var groupResult2 = queryable.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)", "new (StringProperty1
 494        /// </code>
 495        /// </example>
 496        [PublicAPI]
 497        public static IQueryable GroupBy([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] s
 5498        {
 5499            Check.NotNull(source, nameof(source));
 5500            Check.NotEmpty(keySelector, nameof(keySelector));
 5501            Check.NotEmpty(resultSelector, nameof(resultSelector));
 502
 3503            return outer.Provider.CreateQuery(optimized);
 3504        }
 505
 506        /// <summary>
 507        /// Correlates the elements of two sequences based on matching keys. The default equality comparer is used to co
 508        /// </summary>
 509        /// <typeparam name="TElement">The type of the elements of both sequences, and the result.</typeparam>
 510        /// <param name="outer">The first sequence to join.</param>
 511        /// <param name="inner">The sequence to join to the first sequence.</param>
 512        /// <param name="outerKeySelector">A dynamic function to extract the join key from each element of the first seq
 513        /// <param name="innerKeySelector">A dynamic function to extract the join key from each element of the second se
 514        /// <param name="resultSelector">A dynamic function to create a result element from two matching elements.</para
 515        /// <param name="args">An object array that contains zero or more objects to insert into the predicates as param
 516        /// <remarks>This overload only works on elements where both sequences and the resulting element match.</remarks
 517        /// <returns>An <see cref="IQueryable{T}"/> that has elements of type TResult obtained by performing an inner jo
 518        public static IQueryable<TElement> Join<TElement>([NotNull] this IQueryable<TElement> outer, [NotNull] IEnumerab
 0519        {
 0520            return (IQueryable<TElement>)Join((IQueryable)outer, (IEnumerable)inner, outerKeySelector, innerKeySelector,
 0521        }
 522        #endregion Join
 523
 524        #region Last
 1525        private static readonly MethodInfo _last = GetMethod(nameof(Queryable.Last));
 526        /// <summary>
 527        /// Returns the last element of a sequence.
 528        /// </summary>
 529        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 530        /// <returns>The last element in source.</returns>
 531#if NET35
 532        public static object Last([NotNull] this IQueryable source)
 533#else
 534        public static dynamic Last([NotNull] this IQueryable source)
 535#endif
 1536        {
 1537            Check.NotNull(source, nameof(source));
 538
 1539            return Execute(_last, source);
 1540        }
 541        #endregion Last
 5503            bool createParameterCtor = source.IsLinqToObjects();
 5504            LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.Element
 5505            LambdaExpression elementLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.Ele
 506
 5507            var optimized = OptimizeExpression(Expression.Call(
 5508                typeof(Queryable), nameof(Queryable.GroupBy),
 5509                new[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
 5510                source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));
 511
 5512            return source.Provider.CreateQuery(optimized);
 5513        }
 514
 515        /// <inheritdoc cref="GroupBy(IQueryable, ParsingConfig, string, string, object[])"/>
 516        [PublicAPI]
 517        public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [NotNull] strin
 0518        {
 0519            return GroupBy(source, null, keySelector, resultSelector, args);
 0520        }
 521
 522        /// <summary>
 523        /// Groups the elements of a sequence according to a specified key string function
 524        /// and creates a result value from each group and its key.
 525        /// </summary>
 526        /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param>
 527        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 528        /// <param name="keySelector">A string expression to specify the key for each element.</param>
 529        /// <param name="resultSelector">A string expression to specify a result value from each group.</param>
 530        /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</re
 531        /// <example>
 532        /// <code>
 533        /// var groupResult1 = queryable.GroupBy("NumberPropertyAsKey", "StringProperty");
 534        /// var groupResult2 = queryable.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)", "new (StringProperty1
 535        /// </code>
 536        /// </example>
 537        public static IQueryable GroupBy([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] s
 8538        {
 8539            Check.NotNull(source, nameof(source));
 8540            Check.NotEmpty(keySelector, nameof(keySelector));
 8541            Check.NotEmpty(resultSelector, nameof(resultSelector));
 542
 543        #region LastOrDefault
 1544        private static readonly MethodInfo _lastDefault = GetMethod(nameof(Queryable.LastOrDefault));
 545        /// <summary>
 546        /// Returns the last element of a sequence, or a default value if the sequence contains no elements.
 547        /// </summary>
 548        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 549        /// <returns>default if source is empty; otherwise, the last element in source.</returns>
 550#if NET35
 551        public static object LastOrDefault([NotNull] this IQueryable source)
 552#else
 553        public static dynamic LastOrDefault([NotNull] this IQueryable source)
 554#endif
 1555        {
 1556            Check.NotNull(source, nameof(source));
 557
 1558            return Execute(_lastDefault, source);
 1559        }
 560        #endregion LastOrDefault
 561
 562        #region OrderBy
 563        /// <summary>
 564        /// Sorts the elements of a sequence in ascending or descending order according to a key.
 565        /// </summary>
 566        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
 567        /// <param name="source">A sequence of values to order.</param>
 568        /// <param name="ordering">An expression string to indicate values to order by.</param>
 569        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 570        /// <returns>A <see cref="IQueryable{T}"/> whose elements are sorted according to the specified <paramref name="
 571        /// <example>
 572        /// <code>
 573        /// <![CDATA[
 574        /// var resultSingle = queryable.OrderBy<User>("NumberProperty");
 575        /// var resultSingleDescending = queryable.OrderBy<User>("NumberProperty DESC");
 576        /// var resultMultiple = queryable.OrderBy<User>("NumberProperty, StringProperty");
 577        /// ]]>
 578        /// </code>
 579        /// </example>
 580        public static IOrderedQueryable<TSource> OrderBy<TSource>([NotNull] this IQueryable<TSource> source, [NotNull] s
 15581        {
 15582            return (IOrderedQueryable<TSource>)OrderBy((IQueryable)source, ordering, args);
 11583        }
 584
 585        /// <summary>
 586        /// Sorts the elements of a sequence in ascending or descending order according to a key.
 587        /// </summary>
 588        /// <param name="source">A sequence of values to order.</param>
 589        /// <param name="ordering">An expression string to indicate values to order by.</param>
 590        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 591        /// <returns>A <see cref="IQueryable"/> whose elements are sorted according to the specified <paramref name="ord
 592        /// <example>
 593        /// <code>
 594        /// var resultSingle = queryable.OrderBy("NumberProperty");
 595        /// var resultSingleDescending = queryable.OrderBy("NumberProperty DESC");
 596        /// var resultMultiple = queryable.OrderBy("NumberProperty, StringProperty DESC");
 597        /// </code>
 598        /// </example>
 599        public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [NotNull] string ordering, params obje
 24600        {
 24601            Check.NotNull(source, nameof(source));
 23602            Check.NotEmpty(ordering, nameof(ordering));
 603
 20604            ParameterExpression[] parameters = { Expression.Parameter(source.ElementType, "") };
 20605            ExpressionParser parser = new ExpressionParser(parameters, ordering, args);
 20606            IList<DynamicOrdering> dynamicOrderings = parser.ParseOrdering();
 607
 19608            Expression queryExpr = source.Expression;
 609
 101610            foreach (DynamicOrdering dynamicOrdering in dynamicOrderings)
 22611            {
 22612                queryExpr = Expression.Call(
 22613                    typeof(Queryable), dynamicOrdering.MethodName,
 22614                    new[] { source.ElementType, dynamicOrdering.Selector.Type },
 22615                    queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)));
 22616            }
 617
 19618            var optimized = OptimizeExpression(queryExpr);
 19619            return (IOrderedQueryable)source.Provider.CreateQuery(optimized);
 19620        }
 621        #endregion OrderBy
 622
 623        #region Page/PageResult
 624        /// <summary>
 625        /// Returns the elements as paged.
 626        /// </summary>
 627        /// <param name="source">The IQueryable to return elements from.</param>
 628        /// <param name="page">The page to return.</param>
 629        /// <param name="pageSize">The number of elements per page.</param>
 630        /// <returns>A <see cref="IQueryable"/> that contains the paged elements.</returns>
 631        public static IQueryable Page([NotNull] this IQueryable source, int page, int pageSize)
 4632        {
 4633            Check.NotNull(source, nameof(source));
 8634            Check.Condition(page, p => p > 0, nameof(page));
 8635            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 636
 4637            return source.Skip((page - 1) * pageSize).Take(pageSize);
 4638        }
 639
 640        /// <summary>
 641        /// Returns the elements as paged.
 642        /// </summary>
 643        /// <typeparam name="TSource">The type of the source.</typeparam>
 644        /// <param name="source">The IQueryable to return elements from.</param>
 645        /// <param name="page">The page to return.</param>
 646        /// <param name="pageSize">The number of elements per page.</param>
 647        /// <returns>A <see cref="IQueryable{TSource}"/> that contains the paged elements.</returns>
 648        public static IQueryable<TSource> Page<TSource>([NotNull] this IQueryable<TSource> source, int page, int pageSiz
 4649        {
 4650            Check.NotNull(source, nameof(source));
 8651            Check.Condition(page, p => p > 0, nameof(page));
 8652            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 653
 4654            return Queryable.Take(Queryable.Skip(source, (page - 1) * pageSize), pageSize);
 4655        }
 656
 657        /// <summary>
 658        /// Returns the elements as paged and include the CurrentPage, PageCount, PageSize and RowCount.
 659        /// </summary>
 660        /// <param name="source">The IQueryable to return elements from.</param>
 661        /// <param name="page">The page to return.</param>
 662        /// <param name="pageSize">The number of elements per page.</param>
 663        /// <returns>PagedResult</returns>
 664        public static PagedResult PageResult([NotNull] this IQueryable source, int page, int pageSize)
 2665        {
 2666            Check.NotNull(source, nameof(source));
 4667            Check.Condition(page, p => p > 0, nameof(page));
 4668            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 669
 2670            var result = new PagedResult
 2671            {
 2672                CurrentPage = page,
 2673                PageSize = pageSize,
 2674                RowCount = source.Count()
 2675            };
 676
 2677            result.PageCount = (int)Math.Ceiling((double)result.RowCount / pageSize);
 2678            result.Queryable = Page(source, page, pageSize);
 5543            return GroupBy(source, config, keySelector, resultSelector, null);
 5544        }
 545
 546        /// <inheritdoc cref="GroupBy(IQueryable, ParsingConfig, string, string)"/>
 547        public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [NotNull] strin
 8548        {
 8549            return GroupBy(source, null, keySelector, resultSelector);
 5550        }
 551
 552        /// <summary>
 553        /// Groups the elements of a sequence according to a specified key string function
 554        /// and creates a result value from each group and its key.
 555        /// </summary>
 556        /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param>
 557        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 558        /// <param name="keySelector">A string expression to specify the key for each element.</param>
 559        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 560        /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</re
 561        /// <example>
 562        /// <code>
 563        /// var groupResult1 = queryable.GroupBy("NumberPropertyAsKey");
 564        /// var groupResult2 = queryable.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)");
 565        /// </code>
 566        /// </example>
 567        [PublicAPI]
 568        public static IQueryable GroupBy([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] s
 18569        {
 18570            Check.NotNull(source, nameof(source));
 17571            Check.NotEmpty(keySelector, nameof(keySelector));
 572
 14573            bool createParameterCtor = source.IsLinqToObjects();
 14574            LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.Element
 575
 9576            var optimized = OptimizeExpression(Expression.Call(
 9577                typeof(Queryable), nameof(Queryable.GroupBy),
 9578                new[] { source.ElementType, keyLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda)));
 579
 9580            return source.Provider.CreateQuery(optimized);
 9581        }
 582
 583        /// <inheritdoc cref="GroupBy(IQueryable, ParsingConfig, string, object[])"/>
 584        [PublicAPI]
 585        public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [CanBeNull] par
 17586        {
 17587            return GroupBy(source, (ParsingConfig)null, keySelector, args);
 8588        }
 589
 590        #endregion GroupBy
 591
 592        #region GroupByMany
 593        /// <summary>
 594        /// Groups the elements of a sequence according to multiple specified key string functions
 595        /// and creates a result value from each group (and subgroups) and its key.
 596        /// </summary>
 597        /// <typeparam name="TElement"></typeparam>
 598        /// <param name="source">A <see cref="IEnumerable{T}"/> whose elements to group.</param>
 599        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 600        /// <param name="keySelectors"><see cref="string"/> expressions to specify the keys for each element.</param>
 601        /// <returns>A <see cref="IEnumerable{T}"/> of type <see cref="GroupResult"/> where each element represents a pr
 602        public static IEnumerable<GroupResult> GroupByMany<TElement>([NotNull] this IEnumerable<TElement> source, [CanBe
 1603        {
 1604            Check.NotNull(source, nameof(source));
 1605            Check.HasNoNulls(keySelectors, nameof(keySelectors));
 606
 1607            var selectors = new List<Func<TElement, object>>(keySelectors.Length);
 608
 1609            bool createParameterCtor = true;
 7610            foreach (var selector in keySelectors)
 2611            {
 2612                LambdaExpression l = DynamicExpressionParser.ParseLambda(config, createParameterCtor, typeof(TElement), 
 2613                selectors.Add((Func<TElement, object>)l.Compile());
 2614            }
 615
 1616            return GroupByManyInternal(source, selectors.ToArray(), 0);
 1617        }
 618
 619        /// <inheritdoc cref="GroupByMany{TElement}(IEnumerable{TElement}, ParsingConfig, string[])"/>
 620        public static IEnumerable<GroupResult> GroupByMany<TElement>([NotNull] this IEnumerable<TElement> source, params
 1621        {
 1622            return GroupByMany(source, null, keySelectors);
 1623        }
 624
 625        /// <summary>
 626        /// Groups the elements of a sequence according to multiple specified key functions
 627        /// and creates a result value from each group (and subgroups) and its key.
 628        /// </summary>
 629        /// <typeparam name="TElement"></typeparam>
 630        /// <param name="source">A <see cref="IEnumerable{T}"/> whose elements to group.</param>
 631        /// <param name="keySelectors">Lambda expressions to specify the keys for each element.</param>
 632        /// <returns>A <see cref="IEnumerable{T}"/> of type <see cref="GroupResult"/> where each element represents a pr
 633        public static IEnumerable<GroupResult> GroupByMany<TElement>([NotNull] this IEnumerable<TElement> source, params
 1634        {
 1635            Check.NotNull(source, nameof(source));
 1636            Check.HasNoNulls(keySelectors, nameof(keySelectors));
 637
 1638            return GroupByManyInternal(source, keySelectors, 0);
 1639        }
 640
 641        static IEnumerable<GroupResult> GroupByManyInternal<TElement>(IEnumerable<TElement> source, Func<TElement, objec
 15642        {
 21643             if (currentSelector >= keySelectors.Length) return null;
 644
 9645            var selector = keySelectors[currentSelector];
 646
 9647            var result = source.GroupBy(selector).Select(
 22648                g => new GroupResult
 22649                {
 22650                    Key = g.Key,
 22651                    Count = g.Count(),
 22652                    Items = g,
 22653                    Subgroups = GroupByManyInternal(g, keySelectors, currentSelector + 1)
 22654                });
 655
 9656            return result;
 15657        }
 658        #endregion GroupByMany
 659
 660        #region GroupJoin
 661        /// <summary>
 662        /// Correlates the elements of two sequences based on equality of keys and groups the results. The default equal
 663        /// </summary>
 664        /// <param name="outer">The first sequence to join.</param>
 665        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 666        /// <param name="inner">The sequence to join to the first sequence.</param>
 667        /// <param name="outerKeySelector">A dynamic function to extract the join key from each element of the first seq
 668        /// <param name="innerKeySelector">A dynamic function to extract the join key from each element of the second se
 669        /// <param name="resultSelector">A dynamic function to create a result element from an element from the first se
 670        /// <param name="args">An object array that contains zero or more objects to insert into the predicates as param
 671        /// <returns>An <see cref="IQueryable"/> obtained by performing a grouped join on two sequences.</returns>
 672        public static IQueryable GroupJoin([NotNull] this IQueryable outer, [CanBeNull] ParsingConfig config, [NotNull] 
 6673        {
 6674            Check.NotNull(outer, nameof(outer));
 6675            Check.NotNull(inner, nameof(inner));
 6676            Check.NotEmpty(outerKeySelector, nameof(outerKeySelector));
 6677            Check.NotEmpty(innerKeySelector, nameof(innerKeySelector));
 6678            Check.NotEmpty(resultSelector, nameof(resultSelector));
 679
 2680            return result;
 2681        }
 6680            Type outerType = outer.ElementType;
 6681            Type innerType = inner.AsQueryable().ElementType;
 682
 683        /// <summary>
 684        /// Returns the elements as paged and include the CurrentPage, PageCount, PageSize and RowCount.
 685        /// </summary>
 686        /// <typeparam name="TSource">The type of the source.</typeparam>
 687        /// <param name="source">The IQueryable to return elements from.</param>
 688        /// <param name="page">The page to return.</param>
 689        /// <param name="pageSize">The number of elements per page.</param>
 690        /// <returns>PagedResult{TSource}</returns>
 691        public static PagedResult<TSource> PageResult<TSource>([NotNull] this IQueryable<TSource> source, int page, int 
 2692        {
 2693            Check.NotNull(source, nameof(source));
 4694            Check.Condition(page, p => p > 0, nameof(page));
 4695            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 6683            bool createParameterCtor = outer.IsLinqToObjects();
 6684            LambdaExpression outerSelectorLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, oute
 6685            LambdaExpression innerSelectorLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, inne
 686
 6687            CheckOuterAndInnerTypes(createParameterCtor, outerType, innerType, outerKeySelector, innerKeySelector, ref o
 688
 5689            ParameterExpression[] parameters =
 5690            {
 5691                ParameterExpressionHelper.CreateParameterExpression(outerType, "outer"),
 5692                ParameterExpressionHelper.CreateParameterExpression(typeof(IEnumerable<>).MakeGenericType(innerType), "i
 5693            };
 694
 5695            LambdaExpression resultSelectorLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, par
 696
 2697            var result = new PagedResult<TSource>
 2698            {
 2699                CurrentPage = page,
 2700                PageSize = pageSize,
 2701                RowCount = Queryable.Count(source)
 2702            };
 703
 2704            result.PageCount = (int)Math.Ceiling((double)result.RowCount / pageSize);
 2705            result.Queryable = Page(source, page, pageSize);
 5697            return outer.Provider.CreateQuery(Expression.Call(
 5698                typeof(Queryable), nameof(Queryable.GroupJoin),
 5699                new[] { outer.ElementType, innerType, outerSelectorLambda.Body.Type, resultSelectorLambda.Body.Type },
 5700                outer.Expression,
 5701                Expression.Constant(inner),
 5702                Expression.Quote(outerSelectorLambda),
 5703                Expression.Quote(innerSelectorLambda),
 5704                Expression.Quote(resultSelectorLambda)));
 5705        }
 706
 2707            return result;
 2708        }
 709        #endregion Page/PageResult
 710
 711        #region Reverse
 712        /// <summary>
 713        /// Inverts the order of the elements in a sequence.
 714        /// </summary>
 715        /// <param name="source">A sequence of values to reverse.</param>
 716        /// <returns>A <see cref="IQueryable"/> whose elements correspond to those of the input sequence in reverse orde
 717        public static IQueryable Reverse([NotNull] this IQueryable source)
 1718        {
 1719            Check.NotNull(source, nameof(source));
 720
 1721            return Queryable.Reverse((IQueryable<object>)source);
 1722        }
 723        #endregion Reverse
 724
 725        #region Select
 726        /// <summary>
 727        /// Projects each element of a sequence into a new form.
 728        /// </summary>
 729        /// <param name="source">A sequence of values to project.</param>
 730        /// <param name="selector">A projection string expression to apply to each element.</param>
 731        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 732        /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a projection string on each e
 733        /// <example>
 734        /// <code>
 735        /// var singleField = queryable.Select("StringProperty");
 736        /// var dynamicObject = queryable.Select("new (StringProperty1, StringProperty2 as OtherStringPropertyName)");
 737        /// </code>
 738        /// </example>
 739        public static IQueryable Select([NotNull] this IQueryable source, [NotNull] string selector, params object[] arg
 83740        {
 83741            Check.NotNull(source, nameof(source));
 82742            Check.NotEmpty(selector, nameof(selector));
 707        /// <inheritdoc cref="GroupJoin(IQueryable, IEnumerable, string, string, string, object[])"/>
 708        public static IQueryable GroupJoin([NotNull] this IQueryable outer, [NotNull] IEnumerable inner, [NotNull] strin
 6709        {
 6710            return GroupJoin(outer, null, inner, outerKeySelector, innerKeySelector, resultSelector, args);
 5711        }
 712
 713        #endregion
 714
 715        #region Join
 716        /// <summary>
 717        /// Correlates the elements of two sequences based on matching keys. The default equality comparer is used to co
 718        /// </summary>
 719        /// <param name="outer">The first sequence to join.</param>
 720        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 721        /// <param name="inner">The sequence to join to the first sequence.</param>
 722        /// <param name="outerKeySelector">A dynamic function to extract the join key from each element of the first seq
 723        /// <param name="innerKeySelector">A dynamic function to extract the join key from each element of the second se
 724        /// <param name="resultSelector">A dynamic function to create a result element from two matching elements.</para
 725        /// <param name="args">An object array that contains zero or more objects to insert into the predicates as param
 726        /// <returns>An <see cref="IQueryable"/> obtained by performing an inner join on two sequences.</returns>
 727        public static IQueryable Join([NotNull] this IQueryable outer, [CanBeNull] ParsingConfig config, [NotNull] IEnum
 4728        {
 729            //http://stackoverflow.com/questions/389094/how-to-create-a-dynamic-linq-join-extension-method
 730
 4731            Check.NotNull(outer, nameof(outer));
 4732            Check.NotNull(inner, nameof(inner));
 4733            Check.NotEmpty(outerKeySelector, nameof(outerKeySelector));
 4734            Check.NotEmpty(innerKeySelector, nameof(innerKeySelector));
 4735            Check.NotEmpty(resultSelector, nameof(resultSelector));
 736
 4737            Type outerType = outer.ElementType;
 4738            Type innerType = inner.AsQueryable().ElementType;
 739
 4740            bool createParameterCtor = outer.IsLinqToObjects();
 4741            LambdaExpression outerSelectorLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, oute
 4742            LambdaExpression innerSelectorLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, inne
 743
 79744            bool createParameterCtor = source.IsLinqToObjects();
 79745            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 746
 72747            var optimized = OptimizeExpression(Expression.Call(
 72748                typeof(Queryable), nameof(Queryable.Select),
 72749                new[] { source.ElementType, lambda.Body.Type },
 72750                source.Expression, Expression.Quote(lambda))
 72751            );
 752
 72753            return source.Provider.CreateQuery(optimized);
 72754        }
 755
 756        /// <summary>
 757        /// Projects each element of a sequence into a new class of type TResult.
 758        /// Details see <see href="http://solutionizing.net/category/linq/"/>.
 759        /// </summary>
 760        /// <typeparam name="TResult">The type of the result.</typeparam>
 761        /// <param name="source">A sequence of values to project.</param>
 762        /// <param name="selector">A projection string expression to apply to each element.</param>
 763        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 764        /// <returns>An <see cref="IQueryable{TResult}"/> whose elements are the result of invoking a projection string 
 765        /// <example>
 766        /// <code language="cs">
 767        /// <![CDATA[
 768        /// var users = queryable.Select<User>("new (Username, Pwd as Password)");
 769        /// ]]>
 770        /// </code>
 771        /// </example>
 772        public static IQueryable<TResult> Select<TResult>([NotNull] this IQueryable source, [NotNull] string selector, p
 16773        {
 16774            Check.NotNull(source, nameof(source));
 16775            Check.NotEmpty(selector, nameof(selector));
 776
 16777            bool createParameterCtor = source.IsLinqToObjects();
 16778            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, typeo
 779
 16780            var optimized = OptimizeExpression(Expression.Call(
 16781                typeof(Queryable), nameof(Queryable.Select),
 16782                new[] { source.ElementType, typeof(TResult) },
 16783                source.Expression, Expression.Quote(lambda)));
 784
 16785            return source.Provider.CreateQuery<TResult>(optimized);
 16786        }
 787
 788        /// <summary>
 789        /// Projects each element of a sequence into a new class of type TResult.
 790        /// Details see http://solutionizing.net/category/linq/
 791        /// </summary>
 792        /// <param name="source">A sequence of values to project.</param>
 793        /// <param name="resultType">The result type.</param>
 794        /// <param name="selector">A projection string expression to apply to each element.</param>
 795        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 796        /// <returns>An <see cref="IQueryable{TResult}"/> whose elements are the result of invoking a projection string 
 797        /// <example>
 798        /// <code>
 799        /// var users = queryable.Select(typeof(User), "new (Username, Pwd as Password)");
 800        /// </code>
 801        /// </example>
 802        public static IQueryable Select([NotNull] this IQueryable source, [NotNull] Type resultType, [NotNull] string se
 3803        {
 3804            Check.NotNull(source, nameof(source));
 3805            Check.NotNull(resultType, nameof(resultType));
 3806            Check.NotEmpty(selector, nameof(selector));
 807
 3808            bool createParameterCtor = source.IsLinqToObjects();
 3809            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, resul
 810
 3811            var optimized = OptimizeExpression(Expression.Call(
 3812                typeof(Queryable), nameof(Queryable.Select),
 3813                new[] { source.ElementType, resultType },
 3814                source.Expression, Expression.Quote(lambda)));
 4744            CheckOuterAndInnerTypes(createParameterCtor, outerType, innerType, outerKeySelector, innerKeySelector, ref o
 745
 3746            ParameterExpression[] parameters =
 3747            {
 3748                ParameterExpressionHelper.CreateParameterExpression(outerType, "outer"),
 3749                ParameterExpressionHelper.CreateParameterExpression(innerType, "inner")
 3750            };
 751
 3752            LambdaExpression resultSelectorLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, par
 753
 3754            var optimized = OptimizeExpression(Expression.Call(
 3755                typeof(Queryable), "Join",
 3756                new[] { outerType, innerType, outerSelectorLambda.Body.Type, resultSelectorLambda.Body.Type },
 3757                outer.Expression, // outer: The first sequence to join.
 3758                inner.AsQueryable().Expression, // inner: The sequence to join to the first sequence.
 3759                Expression.Quote(outerSelectorLambda), // outerKeySelector: A function to extract the join key from each
 3760                Expression.Quote(innerSelectorLambda), // innerKeySelector: A function to extract the join key from each
 3761                Expression.Quote(resultSelectorLambda) // resultSelector: A function to create a result element from two
 3762            ));
 763
 3764            return outer.Provider.CreateQuery(optimized);
 3765        }
 766
 767        /// <inheritdoc cref="Join(IQueryable, ParsingConfig, IEnumerable, string, string, string, object[])"/>
 768        public static IQueryable Join([NotNull] this IQueryable outer, [NotNull] IEnumerable inner, [NotNull] string out
 4769        {
 4770            return Join(outer, null, inner, outerKeySelector, innerKeySelector, resultSelector, args);
 3771        }
 772
 773        /// <summary>
 774        /// Correlates the elements of two sequences based on matching keys. The default equality comparer is used to co
 775        /// </summary>
 776        /// <typeparam name="TElement">The type of the elements of both sequences, and the result.</typeparam>
 777        /// <param name="outer">The first sequence to join.</param>
 778        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 779        /// <param name="inner">The sequence to join to the first sequence.</param>
 780        /// <param name="outerKeySelector">A dynamic function to extract the join key from each element of the first seq
 781        /// <param name="innerKeySelector">A dynamic function to extract the join key from each element of the second se
 782        /// <param name="resultSelector">A dynamic function to create a result element from two matching elements.</para
 783        /// <param name="args">An object array that contains zero or more objects to insert into the predicates as param
 784        /// <remarks>This overload only works on elements where both sequences and the resulting element match.</remarks
 785        /// <returns>An <see cref="IQueryable{T}"/> that has elements of type TResult obtained by performing an inner jo
 786        public static IQueryable<TElement> Join<TElement>([NotNull] this IQueryable<TElement> outer, [CanBeNull] Parsing
 0787        {
 0788            return (IQueryable<TElement>)Join(outer, config, (IEnumerable)inner, outerKeySelector, innerKeySelector, res
 0789        }
 790
 791        /// <inheritdoc cref="Join{TElement}(IQueryable{TElement}, ParsingConfig, IEnumerable{TElement}, string, string,
 792        public static IQueryable<TElement> Join<TElement>([NotNull] this IQueryable<TElement> outer, [NotNull] IEnumerab
 0793        {
 0794            return Join(outer, null, inner, outerKeySelector, innerKeySelector, resultSelector, args);
 0795        }
 796        #endregion Join
 797
 798        #region Last
 1799        private static readonly MethodInfo _last = GetMethod(nameof(Queryable.Last));
 800        /// <summary>
 801        /// Returns the last element of a sequence.
 802        /// </summary>
 803        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 804        /// <returns>The last element in source.</returns>
 805#if NET35
 806        public static object Last([NotNull] this IQueryable source)
 807#else
 808        public static dynamic Last([NotNull] this IQueryable source)
 809#endif
 5810        {
 5811            Check.NotNull(source, nameof(source));
 812
 5813            return Execute(_last, source);
 5814        }
 815
 3816            return source.Provider.CreateQuery(optimized);
 3817        }
 818        #endregion Select
 819
 820        #region SelectMany
 821        /// <summary>
 822        /// Projects each element of a sequence to an <see cref="IQueryable"/> and combines the resulting sequences into
 823        /// </summary>
 824        /// <param name="source">A sequence of values to project.</param>
 825        /// <param name="selector">A projection string expression to apply to each element.</param>
 826        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 827        /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a one-to-many projection func
 828        /// <example>
 829        /// <code>
 830        /// var roles = users.SelectMany("Roles");
 831        /// </code>
 832        /// </example>
 833        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] string selector, params object[]
 13834        {
 13835            Check.NotNull(source, nameof(source));
 13836            Check.NotEmpty(selector, nameof(selector));
 1816        private static readonly MethodInfo _lastPredicate = GetMethod(nameof(Queryable.Last), 1);
 817
 818        /// <summary>
 819        /// Returns the last element of a sequence that satisfies a specified condition.
 820        /// </summary>
 821        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 822        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 823        /// <param name="predicate">A function to test each element for a condition.</param>
 824        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 825        /// <returns>The first element in source that passes the test in predicate.</returns>
 826#if NET35
 827        public static object Last([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string p
 828#else
 829        public static dynamic Last([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string 
 830#endif
 2831        {
 2832            Check.NotNull(source, nameof(source));
 2833            Check.NotEmpty(predicate, nameof(predicate));
 834
 2835            bool createParameterCtor = source.IsLinqToObjects();
 2836            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 837
 13838            return SelectManyInternal(source, null, selector, args);
 11839        }
 2838            return Execute(_lastPredicate, source, lambda);
 2839        }
 840
 841        /// <summary>
 842        /// Projects each element of a sequence to an <see cref="IQueryable"/> and combines the resulting sequences into
 843        /// </summary>
 844        /// <param name="source">A sequence of values to project.</param>
 845        /// <param name="selector">A projection string expression to apply to each element.</param>
 846        /// <param name="resultType">The result type.</param>
 847        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 848        /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a one-to-many projection func
 849        /// <example>
 850        /// <code>
 851        /// var permissions = users.SelectMany(typeof(Permission), "Roles.SelectMany(Permissions)");
 852        /// </code>
 853        /// </example>
 854        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] Type resultType, [NotNull] strin
 2855        {
 2856            Check.NotNull(source, nameof(source));
 2857            Check.NotNull(resultType, nameof(resultType));
 2858            Check.NotEmpty(selector, nameof(selector));
 859
 2860            return SelectManyInternal(source, resultType, selector, args);
 2861        }
 862
 863        private static IQueryable SelectManyInternal(IQueryable source, Type resultType, string selector, params object[
 15864        {
 15865            bool createParameterCtor = source.IsLinqToObjects();
 15866            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 867
 868            //Extra help to get SelectMany to work from StackOverflow Answer
 869            //http://stackoverflow.com/a/3001674/2465182
 870
 871            // if resultType is not specified, create one based on the lambda.Body.Type
 13872             if (resultType == null)
 11873            {
 874                // SelectMany assumes that lambda.Body.Type is a generic type and throws an exception on
 875                // lambda.Body.Type.GetGenericArguments()[0] when used over an array as GetGenericArguments() returns an
 11876                 if (lambda.Body.Type.IsArray)
 6877                    resultType = lambda.Body.Type.GetElementType();
 878                else
 5879                    resultType = lambda.Body.Type.GetGenericArguments()[0];
 11880            }
 881
 882            //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is.
 13883            Type enumerableType = typeof(IEnumerable<>).MakeGenericType(resultType);
 13884            Type inputType = source.Expression.Type.GetTypeInfo().GetGenericTypeArguments()[0];
 13885            Type delegateType = typeof(Func<,>).MakeGenericType(inputType, enumerableType);
 13886            lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters);
 887
 13888            var optimized = OptimizeExpression(Expression.Call(
 13889                typeof(Queryable), "SelectMany",
 13890                new[] { source.ElementType, resultType },
 13891                source.Expression, Expression.Quote(lambda))
 13892            );
 893
 13894            return source.Provider.CreateQuery(optimized);
 13895        }
 896
 897        /// <summary>
 898        /// Projects each element of a sequence to an <see cref="IQueryable{TResult}"/> and combines the resulting seque
 899        /// </summary>
 900        /// <typeparam name="TResult">The type of the result.</typeparam>
 901        /// <param name="source">A sequence of values to project.</param>
 902        /// <param name="selector">A projection string expression to apply to each element.</param>
 903        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 904        /// <returns>An <see cref="IQueryable{TResult}"/> whose elements are the result of invoking a one-to-many projec
 905        /// <example>
 906        /// <code>
 907        /// <![CDATA[
 908        /// var permissions = users.SelectMany<Permission>("Roles.SelectMany(Permissions)");
 909        /// ]]>
 910        /// </code>
 911        /// </example>
 912        public static IQueryable<TResult> SelectMany<TResult>([NotNull] this IQueryable source, [NotNull] string selecto
 2913        {
 2914            Check.NotNull(source, nameof(source));
 2915            Check.NotEmpty(selector, nameof(selector));
 916
 2917            bool createParameterCtor = source.IsLinqToObjects();
 2918            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 919
 920            //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is.
 2921            Type inputType = source.Expression.Type.GetTypeInfo().GetGenericTypeArguments()[0];
 2922            Type enumerableType = typeof(IEnumerable<>).MakeGenericType(typeof(TResult));
 2923            Type delegateType = typeof(Func<,>).MakeGenericType(inputType, enumerableType);
 2924            lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters);
 925
 2926            var optimized = OptimizeExpression(Expression.Call(
 2927                typeof(Queryable), "SelectMany",
 2928                new[] { source.ElementType, typeof(TResult) },
 2929                source.Expression, Expression.Quote(lambda))
 2930            );
 931
 2932            return source.Provider.CreateQuery<TResult>(optimized);
 2933        }
 934
 935        /// <summary>
 936        /// Projects each element of a sequence to an <see cref="IQueryable"/>
 937        /// and invokes a result selector function on each element therein. The resulting
 938        /// values from each intermediate sequence are combined into a single, one-dimensional
 939        /// sequence and returned.
 940        /// </summary>
 941        /// <param name="source">A sequence of values to project.</param>
 942        /// <param name="collectionSelector">A projection function to apply to each element of the input sequence.</para
 943        /// <param name="resultSelector">A projection function to apply to each element of each intermediate sequence. S
 944        /// <param name="collectionSelectorArgs">An object array that contains zero or more objects to insert into the p
 945        /// <param name="resultSelectorArgs">An object array that contains zero or more objects to insert into the predi
 946        /// <returns>
 947        /// An <see cref="IQueryable"/> whose elements are the result of invoking the one-to-many
 948        /// projection function <paramref name="collectionSelector"/> on each element of source and then mapping
 949        /// each of those sequence elements and their corresponding source element to a result element.
 950        /// </returns>
 951        /// <example>
 952        /// <code>
 953        /// <![CDATA[
 954        /// // TODO
 841        /// <inheritdoc cref="Last(IQueryable, ParsingConfig, string, object[])"/>
 842#if NET35
 843        public static object Last([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 844#else
 845        public static dynamic Last([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 846#endif
 1847        {
 1848            return Last(source, null, predicate, args);
 1849        }
 850
 851
 852        /// <summary>
 853        /// Returns the last element of a sequence that satisfies a specified condition.
 854        /// </summary>
 855        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 856        /// <param name="lambda">A cached Lambda Expression.</param>
 857        /// <returns>The first element in source that passes the test in predicate.</returns>
 858#if NET35
 859        public static object Last([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 860#else
 861        public static dynamic Last([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 862#endif
 1863        {
 1864            Check.NotNull(source, nameof(source));
 1865            return Execute(_lastPredicate, source, lambda);
 1866        }
 867        #endregion Last
 868
 869        #region LastOrDefault
 1870        private static readonly MethodInfo _lastDefault = GetMethod(nameof(Queryable.LastOrDefault));
 871        /// <summary>
 872        /// Returns the last element of a sequence, or a default value if the sequence contains no elements.
 873        /// </summary>
 874        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 875        /// <returns>default if source is empty; otherwise, the last element in source.</returns>
 876#if NET35
 877        public static object LastOrDefault([NotNull] this IQueryable source)
 878#else
 879        public static dynamic LastOrDefault([NotNull] this IQueryable source)
 880#endif
 1881        {
 1882            Check.NotNull(source, nameof(source));
 883
 1884            return Execute(_lastDefault, source);
 1885        }
 886
 1887        private static readonly MethodInfo _lastDefaultPredicate = GetMethod(nameof(Queryable.LastOrDefault), 1);
 888
 889        /// <summary>
 890        /// Returns the last element of a sequence that satisfies a specified condition, or a default value if the seque
 891        /// </summary>
 892        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 893        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 894        /// <param name="predicate">A function to test each element for a condition.</param>
 895        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 896        /// <returns>The first element in source that passes the test in predicate.</returns>
 897#if NET35
 898        public static object LastOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull]
 899#else
 900        public static dynamic LastOrDefault([NotNull] this IQueryable source,  [CanBeNull] ParsingConfig config, [NotNul
 901#endif
 2902        {
 2903            Check.NotNull(source, nameof(source));
 2904            Check.NotEmpty(predicate, nameof(predicate));
 905
 2906            bool createParameterCtor = source.IsLinqToObjects();
 2907            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 908
 2909            return Execute(_lastDefaultPredicate, source, lambda);
 2910        }
 911
 912        /// <inheritdoc cref="LastOrDefault(IQueryable, ParsingConfig, string, object[])"/>
 913#if NET35
 914        public static object LastOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[]
 915#else
 916        public static dynamic LastOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object[
 917#endif
 2918        {
 2919            return LastOrDefault(source, null, predicate, args);
 2920        }
 921
 922        /// <summary>
 923        /// Returns the last element of a sequence that satisfies a specified condition, or a default value if the seque
 924        /// </summary>
 925        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 926        /// <param name="lambda">A cached Lambda Expression.</param>
 927        /// <returns>The first element in source that passes the test in predicate.</returns>
 928#if NET35
 929        public static object LastOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 930#else
 931        public static dynamic LastOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 932#endif
 1933        {
 1934            Check.NotNull(source, nameof(source));
 1935            return Execute(_lastDefaultPredicate, source, lambda);
 1936        }
 937        #endregion LastOrDefault
 938
 939        #region OrderBy
 940        /// <summary>
 941        /// Sorts the elements of a sequence in ascending or descending order according to a key.
 942        /// </summary>
 943        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
 944        /// <param name="source">A sequence of values to order.</param>
 945        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 946        /// <param name="ordering">An expression string to indicate values to order by.</param>
 947        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 948        /// <returns>A <see cref="IQueryable{T}"/> whose elements are sorted according to the specified <paramref name="
 949        /// <example>
 950        /// <code>
 951        /// <![CDATA[
 952        /// var resultSingle = queryable.OrderBy<User>("NumberProperty");
 953        /// var resultSingleDescending = queryable.OrderBy<User>("NumberProperty DESC");
 954        /// var resultMultiple = queryable.OrderBy<User>("NumberProperty, StringProperty");
 955        /// ]]>
 956        /// </code>
 957        /// </example>
 958        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] string collectionSelector, [NotN
 1959        {
 1960            return SelectMany(source, collectionSelector, resultSelector, "x", "y", collectionSelectorArgs, resultSelect
 1961        }
 958        public static IOrderedQueryable<TSource> OrderBy<TSource>([NotNull] this IQueryable<TSource> source, [CanBeNull]
 15959        {
 15960            return (IOrderedQueryable<TSource>)OrderBy((IQueryable)source, config, ordering, args);
 11961        }
 962
 963        /// <summary>
 964        /// Projects each element of a sequence to an <see cref="IQueryable"/>
 965        /// and invokes a result selector function on each element therein. The resulting
 966        /// values from each intermediate sequence are combined into a single, one-dimensional
 967        /// sequence and returned.
 968        /// </summary>
 969        /// <param name="source">A sequence of values to project.</param>
 970        /// <param name="collectionSelector">A projection function to apply to each element of the input sequence.</para
 971        /// <param name="collectionParameterName">The name from collectionParameter to use. Default is x.</param>
 972        /// <param name="resultSelector">A projection function to apply to each element of each intermediate sequence.</
 973        /// <param name="resultParameterName">The name from resultParameterName to use. Default is y.</param>
 974        /// <param name="collectionSelectorArgs">An object array that contains zero or more objects to insert into the p
 975        /// <param name="resultSelectorArgs">An object array that contains zero or more objects to insert into the predi
 976        /// <returns>
 977        /// An <see cref="IQueryable"/> whose elements are the result of invoking the one-to-many
 978        /// projection function <paramref name="collectionSelector"/> on each element of source and then mapping
 979        /// each of those sequence elements and their corresponding source element to a result element.
 980        /// </returns>
 981        /// <example>
 982        /// <code>
 983        /// <![CDATA[
 984        /// // TODO
 985        /// ]]>
 986        /// </code>
 987        /// </example>
 988        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] string collectionSelector, [NotN
 989            [NotNull] string collectionParameterName, [NotNull] string resultParameterName, [CanBeNull] object[] collect
 2990        {
 2991            Check.NotNull(source, nameof(source));
 2992            Check.NotEmpty(collectionSelector, nameof(collectionSelector));
 2993            Check.NotEmpty(collectionParameterName, nameof(collectionParameterName));
 2994            Check.NotEmpty(resultSelector, nameof(resultSelector));
 2995            Check.NotEmpty(resultParameterName, nameof(resultParameterName));
 996
 2997            bool createParameterCtor = source.IsLinqToObjects();
 2998            LambdaExpression sourceSelectLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.Elemen
 999
 1000            //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is.
 21001            Type sourceLambdaInputType = source.Expression.Type.GetGenericArguments()[0];
 21002            Type sourceLambdaResultType = sourceSelectLambda.Body.Type.GetGenericArguments()[0];
 21003            Type sourceLambdaEnumerableType = typeof(IEnumerable<>).MakeGenericType(sourceLambdaResultType);
 21004            Type sourceLambdaDelegateType = typeof(Func<,>).MakeGenericType(sourceLambdaInputType, sourceLambdaEnumerabl
 1005
 21006            sourceSelectLambda = Expression.Lambda(sourceLambdaDelegateType, sourceSelectLambda.Body, sourceSelectLambda
 1007
 1008            //we have to create additional lambda for result selection
 21009            ParameterExpression xParameter = Expression.Parameter(source.ElementType, collectionParameterName);
 21010            ParameterExpression yParameter = Expression.Parameter(sourceLambdaResultType, resultParameterName);
 1011
 21012            LambdaExpression resultSelectLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, new[] { xPara
 21013            Type resultLambdaResultType = resultSelectLambda.Body.Type;
 963        /// <inheritdoc cref="OrderBy{TSource}(IQueryable{TSource}, ParsingConfig, string, object[])"/>
 964        public static IOrderedQueryable<TSource> OrderBy<TSource>([NotNull] this IQueryable<TSource> source, [NotNull] s
 15965        {
 15966            return OrderBy(source, null, ordering, args);
 11967        }
 968
 969        /// <summary>
 970        /// Sorts the elements of a sequence in ascending or descending order according to a key.
 971        /// </summary>
 972        /// <param name="source">A sequence of values to order.</param>
 973        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 974        /// <param name="ordering">An expression string to indicate values to order by.</param>
 975        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 976        /// <returns>A <see cref="IQueryable"/> whose elements are sorted according to the specified <paramref name="ord
 977        /// <example>
 978        /// <code>
 979        /// var resultSingle = queryable.OrderBy("NumberProperty");
 980        /// var resultSingleDescending = queryable.OrderBy("NumberProperty DESC");
 981        /// var resultMultiple = queryable.OrderBy("NumberProperty, StringProperty DESC");
 982        /// </code>
 983        /// </example>
 984        public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [Not
 26985        {
 26986            Check.NotNull(source, nameof(source));
 25987            Check.NotEmpty(ordering, nameof(ordering));
 988
 22989            ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(source.ElementType,
 22990            ExpressionParser parser = new ExpressionParser(parameters, ordering, args, config);
 22991            IList<DynamicOrdering> dynamicOrderings = parser.ParseOrdering();
 992
 21993            Expression queryExpr = source.Expression;
 994
 111995            foreach (DynamicOrdering dynamicOrdering in dynamicOrderings)
 24996            {
 24997                queryExpr = Expression.Call(
 24998                    typeof(Queryable), dynamicOrdering.MethodName,
 24999                    new[] { source.ElementType, dynamicOrdering.Selector.Type },
 241000                    queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)));
 241001            }
 1002
 211003            var optimized = OptimizeExpression(queryExpr);
 211004            return (IOrderedQueryable)source.Provider.CreateQuery(optimized);
 211005        }
 1006
 1007        /// <inheritdoc cref="OrderBy(IQueryable, ParsingConfig, string, object[])"/>
 1008        public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [NotNull] string ordering, params obje
 111009        {
 111010            return OrderBy(source, null, ordering, args);
 101011        }
 1012
 1013        #endregion OrderBy
 1014
 21015            var optimized = OptimizeExpression(Expression.Call(
 21016                typeof(Queryable), "SelectMany",
 21017                new[] { source.ElementType, sourceLambdaResultType, resultLambdaResultType },
 21018                source.Expression, Expression.Quote(sourceSelectLambda), Expression.Quote(resultSelectLambda))
 21019            );
 1020
 21021            return source.Provider.CreateQuery(optimized);
 21022        }
 1023        #endregion SelectMany
 1024
 1025        #region Single/SingleOrDefault
 1026        /// <summary>
 1027        /// Returns the only element of a sequence, and throws an exception if there
 1028        /// is not exactly one element in the sequence.
 1029        /// </summary>
 1030        /// <param name="source">A <see cref="IQueryable"/> to return the single element of.</param>
 1031        /// <returns>The single element of the input sequence.</returns>
 1032#if NET35
 1033        public static object Single([NotNull] this IQueryable source)
 1034#else
 1035        public static dynamic Single([NotNull] this IQueryable source)
 1036#endif
 561037        {
 561038            Check.NotNull(source, nameof(source));
 1039
 561040            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "Single", new[] { source.ElementType }
 561041            return source.Provider.Execute(optimized);
 561042        }
 1043
 1044        /// <summary>
 1045        /// Returns the only element of a sequence, or a default value if the sequence
 1046        /// is empty; this method throws an exception if there is more than one element
 1047        /// in the sequence.
 1048        /// </summary>
 1049        /// <param name="source">A <see cref="IQueryable"/> to return the single element of.</param>
 1050        /// <returns>The single element of the input sequence, or default if the sequence contains no elements.</returns
 1051#if NET35
 1052        public static object SingleOrDefault([NotNull] this IQueryable source)
 1053#else
 1054        public static dynamic SingleOrDefault([NotNull] this IQueryable source)
 1055#endif
 21056        {
 21057            Check.NotNull(source, nameof(source));
 1058
 21059            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "SingleOrDefault", new[] { source.Elem
 21060            return source.Provider.Execute(optimized);
 21061        }
 1062        #endregion Single/SingleOrDefault
 1063
 1064        #region Skip
 11065        private static readonly MethodInfo _skip = GetMethod(nameof(Queryable.Skip), 1);
 1066
 1067        /// <summary>
 1068        /// Bypasses a specified number of elements in a sequence and then returns the remaining elements.
 1069        /// </summary>
 1070        /// <param name="source">A <see cref="IQueryable"/> to return elements from.</param>
 1071        /// <param name="count">The number of elements to skip before returning the remaining elements.</param>
 1072        /// <returns>A <see cref="IQueryable"/> that contains elements that occur after the specified index in the input
 1073        public static IQueryable Skip([NotNull] this IQueryable source, int count)
 101074        {
 101075            Check.NotNull(source, nameof(source));
 201076            Check.Condition(count, x => x >= 0, nameof(count));
 1077
 1078            //no need to skip if count is zero
 101079             if (count == 0)
 11080                return source;
 1081
 91082            return CreateQuery(_skip, source, Expression.Constant(count));
 101083        }
 1084        #endregion Skip
 1085
 1086        #region SkipWhile
 11087        private static readonly MethodInfo _skipWhilePredicate = GetMethod(nameof(Queryable.SkipWhile), 1, _predicatePar
 1015        #region Page/PageResult
 1016        /// <summary>
 1017        /// Returns the elements as paged.
 1018        /// </summary>
 1019        /// <param name="source">The IQueryable to return elements from.</param>
 1020        /// <param name="page">The page to return.</param>
 1021        /// <param name="pageSize">The number of elements per page.</param>
 1022        /// <returns>A <see cref="IQueryable"/> that contains the paged elements.</returns>
 1023        public static IQueryable Page([NotNull] this IQueryable source, int page, int pageSize)
 41024        {
 41025            Check.NotNull(source, nameof(source));
 81026            Check.Condition(page, p => p > 0, nameof(page));
 81027            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 1028
 41029            return source.Skip((page - 1) * pageSize).Take(pageSize);
 41030        }
 1031
 1032        /// <summary>
 1033        /// Returns the elements as paged.
 1034        /// </summary>
 1035        /// <typeparam name="TSource">The type of the source.</typeparam>
 1036        /// <param name="source">The IQueryable to return elements from.</param>
 1037        /// <param name="page">The page to return.</param>
 1038        /// <param name="pageSize">The number of elements per page.</param>
 1039        /// <returns>A <see cref="IQueryable{TSource}"/> that contains the paged elements.</returns>
 1040        public static IQueryable<TSource> Page<TSource>([NotNull] this IQueryable<TSource> source, int page, int pageSiz
 41041        {
 41042            Check.NotNull(source, nameof(source));
 81043            Check.Condition(page, p => p > 0, nameof(page));
 81044            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 1045
 41046            return Queryable.Take(Queryable.Skip(source, (page - 1) * pageSize), pageSize);
 41047        }
 1048
 1049        /// <summary>
 1050        /// Returns the elements as paged and include the CurrentPage, PageCount, PageSize and RowCount.
 1051        /// </summary>
 1052        /// <param name="source">The IQueryable to return elements from.</param>
 1053        /// <param name="page">The page to return.</param>
 1054        /// <param name="pageSize">The number of elements per page.</param>
 1055        /// <returns>PagedResult</returns>
 1056        public static PagedResult PageResult([NotNull] this IQueryable source, int page, int pageSize)
 21057        {
 21058            Check.NotNull(source, nameof(source));
 41059            Check.Condition(page, p => p > 0, nameof(page));
 41060            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 1061
 21062            var result = new PagedResult
 21063            {
 21064                CurrentPage = page,
 21065                PageSize = pageSize,
 21066                RowCount = source.Count()
 21067            };
 1068
 21069            result.PageCount = (int)Math.Ceiling((double)result.RowCount / pageSize);
 21070            result.Queryable = Page(source, page, pageSize);
 1071
 21072            return result;
 21073        }
 1074
 1075        /// <summary>
 1076        /// Returns the elements as paged and include the CurrentPage, PageCount, PageSize and RowCount.
 1077        /// </summary>
 1078        /// <typeparam name="TSource">The type of the source.</typeparam>
 1079        /// <param name="source">The IQueryable to return elements from.</param>
 1080        /// <param name="page">The page to return.</param>
 1081        /// <param name="pageSize">The number of elements per page.</param>
 1082        /// <returns>PagedResult{TSource}</returns>
 1083        public static PagedResult<TSource> PageResult<TSource>([NotNull] this IQueryable<TSource> source, int page, int 
 21084        {
 21085            Check.NotNull(source, nameof(source));
 41086            Check.Condition(page, p => p > 0, nameof(page));
 41087            Check.Condition(pageSize, ps => ps > 0, nameof(pageSize));
 1088
 1089        /// <summary>
 1090        /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elem
 1091        /// </summary>
 1092        /// <param name="source">A sequence to check for being empty.</param>
 1093        /// <param name="predicate">A function to test each element for a condition.</param>
 1094        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1095        /// <example>
 1096        /// <code language="cs">
 1097        /// IQueryable queryable = employees.AsQueryable();
 1098        /// var result1 = queryable.SkipWhile("Income > 50");
 1099        /// var result2 = queryable.SkipWhile("Income > @0", 50);
 1100        /// </code>
 1101        /// </example>
 1102        /// <returns>An <see cref="IQueryable"/> that contains elements from source starting at the first element in the
 1103        public static IQueryable SkipWhile([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] par
 21104        {
 21105            Check.NotNull(source, nameof(source));
 21106            Check.NotNull(predicate, nameof(predicate));
 1107
 21108            bool createParameterCtor = source.IsLinqToObjects();
 21109            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 1110
 21111            return CreateQuery(_skipWhilePredicate, source, lambda);
 21112        }
 1113        #endregion SkipWhile
 1114
 1115        #region Sum
 1116        /// <summary>
 1117        /// Computes the sum of a sequence of numeric values.
 1118        /// </summary>
 1119        /// <param name="source">A sequence of numeric values to calculate the sum of.</param>
 1120        /// <returns>The sum of the values in the sequence.</returns>
 1121        public static object Sum([NotNull] this IQueryable source)
 21122        {
 21123            Check.NotNull(source, nameof(source));
 1124
 21125            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "Sum", null, source.Expression));
 21126            return source.Provider.Execute(optimized);
 21127        }
 1128        #endregion Sum
 1129
 1130        #region Take
 11131        private static readonly MethodInfo _take = GetMethod(nameof(Queryable.Take), 1);
 1132        /// <summary>
 1133        /// Returns a specified number of contiguous elements from the start of a sequence.
 1134        /// </summary>
 1135        /// <param name="source">The sequence to return elements from.</param>
 1136        /// <param name="count">The number of elements to return.</param>
 1137        /// <returns>A <see cref="IQueryable"/> that contains the specified number of elements from the start of source.
 1138        public static IQueryable Take([NotNull] this IQueryable source, int count)
 121139        {
 121140            Check.NotNull(source, nameof(source));
 241141            Check.Condition(count, x => x >= 0, nameof(count));
 1142
 121143            return CreateQuery(_take, source, Expression.Constant(count));
 121144        }
 1145        #endregion Take
 1146
 1147        #region TakeWhile
 11148        private static readonly MethodInfo _takeWhilePredicate = GetMethod(nameof(Queryable.TakeWhile), 1, _predicatePar
 1149
 1150        /// <summary>
 1151        /// Returns elements from a sequence as long as a specified condition is true.
 1152        /// </summary>
 1153        /// <param name="source">A sequence to check for being empty.</param>
 1154        /// <param name="predicate">A function to test each element for a condition.</param>
 1155        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1156        /// <example>
 1157        /// <code language="cs">
 1158        /// IQueryable queryable = employees.AsQueryable();
 1159        /// var result1 = queryable.TakeWhile("Income > 50");
 1160        /// var result2 = queryable.TakeWhile("Income > @0", 50);
 1161        /// </code>
 1162        /// </example>
 1163        /// <returns>An <see cref="IQueryable"/> that contains elements from the input sequence occurring before the ele
 1164        public static IQueryable TakeWhile([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] par
 21165        {
 21166            Check.NotNull(source, nameof(source));
 21167            Check.NotNull(predicate, nameof(predicate));
 1168
 21169            bool createParameterCtor = source.IsLinqToObjects();
 21170            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 1171
 21172            return CreateQuery(_takeWhilePredicate, source, lambda);
 21173        }
 1174        #endregion TakeWhile
 1175
 1176        #region ThenBy
 1177        /// <summary>
 1178        /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
 1179        /// </summary>
 1180        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
 1181        /// <param name="source">A sequence of values to order.</param>
 1182        /// <param name="ordering">An expression string to indicate values to order by.</param>
 1183        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1184        /// <returns>A <see cref="IOrderedQueryable{T}"/> whose elements are sorted according to the specified <paramref
 1185        /// <example>
 1186        /// <code>
 1187        /// <![CDATA[
 1188        /// var result = queryable.OrderBy<User>("LastName");
 1189        /// var resultSingle = result.ThenBy<User>("NumberProperty");
 1190        /// var resultSingleDescending = result.ThenBy<User>("NumberProperty DESC");
 1191        /// var resultMultiple = result.ThenBy<User>("NumberProperty, StringProperty");
 1192        /// ]]>
 1193        /// </code>
 1194        /// </example>
 1195        public static IOrderedQueryable<TSource> ThenBy<TSource>([NotNull] this IOrderedQueryable<TSource> source, [NotN
 61196        {
 61197            return (IOrderedQueryable<TSource>)ThenBy((IOrderedQueryable)source, ordering, args);
 21198        }
 1199
 1200        /// <summary>
 1201        /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
 1202        /// </summary>
 1203        /// <param name="source">A sequence of values to order.</param>
 1204        /// <param name="ordering">An expression string to indicate values to order by.</param>
 1205        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1206        /// <returns>A <see cref="IQueryable"/> whose elements are sorted according to the specified <paramref name="ord
 1207        /// <example>
 1208        /// <code>
 1209        /// var result = queryable.OrderBy("LastName");
 1210        /// var resultSingle = result.OrderBy("NumberProperty");
 1211        /// var resultSingleDescending = result.OrderBy("NumberProperty DESC");
 1212        /// var resultMultiple = result.OrderBy("NumberProperty, StringProperty DESC");
 1213        /// </code>
 1214        /// </example>
 1215        public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source, [NotNull] string ordering, param
 71216        {
 71217            Check.NotNull(source, nameof(source));
 61218            Check.NotEmpty(ordering, nameof(ordering));
 1219
 31220            ParameterExpression[] parameters = { Expression.Parameter(source.ElementType, "") };
 31221            ExpressionParser parser = new ExpressionParser(parameters, ordering, args);
 31222            IList<DynamicOrdering> dynamicOrderings = parser.ParseOrdering(forceThenBy: true);
 1223
 21224            Expression queryExpr = source.Expression;
 21089            var result = new PagedResult<TSource>
 21090            {
 21091                CurrentPage = page,
 21092                PageSize = pageSize,
 21093                RowCount = Queryable.Count(source)
 21094            };
 1095
 21096            result.PageCount = (int)Math.Ceiling((double)result.RowCount / pageSize);
 21097            result.Queryable = Page(source, page, pageSize);
 1098
 21099            return result;
 21100        }
 1101        #endregion Page/PageResult
 1102
 1103        #region Reverse
 1104        /// <summary>
 1105        /// Inverts the order of the elements in a sequence.
 1106        /// </summary>
 1107        /// <param name="source">A sequence of values to reverse.</param>
 1108        /// <returns>A <see cref="IQueryable"/> whose elements correspond to those of the input sequence in reverse orde
 1109        public static IQueryable Reverse([NotNull] this IQueryable source)
 11110        {
 11111            Check.NotNull(source, nameof(source));
 1112
 11113            return Queryable.Reverse((IQueryable<object>)source);
 11114        }
 1115        #endregion Reverse
 1116
 1117        #region Select
 1118        /// <summary>
 1119        /// Projects each element of a sequence into a new form.
 1120        /// </summary>
 1121        /// <param name="source">A sequence of values to project.</param>
 1122        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1123        /// <param name="selector">A projection string expression to apply to each element.</param>
 1124        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1125        /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a projection string on each e
 1126        /// <example>
 1127        /// <code>
 1128        /// var singleField = queryable.Select("StringProperty");
 1129        /// var dynamicObject = queryable.Select("new (StringProperty1, StringProperty2 as OtherStringPropertyName)");
 1130        /// </code>
 1131        /// </example>
 1132        public static IQueryable Select([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] st
 941133        {
 941134            Check.NotNull(source, nameof(source));
 931135            Check.NotEmpty(selector, nameof(selector));
 1136
 901137            bool createParameterCtor = source.IsLinqToObjects();
 901138            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1139
 811140            var optimized = OptimizeExpression(Expression.Call(
 811141                typeof(Queryable), nameof(Queryable.Select),
 811142                new[] { source.ElementType, lambda.Body.Type },
 811143                source.Expression, Expression.Quote(lambda))
 811144            );
 1145
 811146            return source.Provider.CreateQuery(optimized);
 811147        }
 1148
 1149        /// <inheritdoc cref="Select(IQueryable, ParsingConfig, string, object[])"/>
 1150        public static IQueryable Select([NotNull] this IQueryable source, [NotNull] string selector, params object[] arg
 941151        {
 941152            return Select(source, (ParsingConfig)null, selector, args);
 811153        }
 1154
 1155        /// <summary>
 1156        /// Projects each element of a sequence into a new class of type TResult.
 1157        /// Details see <see href="http://solutionizing.net/category/linq/"/>.
 1158        /// </summary>
 1159        /// <typeparam name="TResult">The type of the result.</typeparam>
 1160        /// <param name="source">A sequence of values to project.</param>
 1161        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1162        /// <param name="selector">A projection string expression to apply to each element.</param>
 1163        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1164        /// <returns>An <see cref="IQueryable{TResult}"/> whose elements are the result of invoking a projection string 
 1165        /// <example>
 1166        /// <code language="cs">
 1167        /// <![CDATA[
 1168        /// var users = queryable.Select<User>("new (Username, Pwd as Password)");
 1169        /// ]]>
 1170        /// </code>
 1171        /// </example>
 1172        public static IQueryable<TResult> Select<TResult>([NotNull] this IQueryable source, [CanBeNull] ParsingConfig co
 271173        {
 271174            Check.NotNull(source, nameof(source));
 271175            Check.NotEmpty(selector, nameof(selector));
 1176
 271177            bool createParameterCtor = source.IsLinqToObjects();
 271178            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1179
 271180            var optimized = OptimizeExpression(Expression.Call(
 271181                typeof(Queryable), nameof(Queryable.Select),
 271182                new[] { source.ElementType, typeof(TResult) },
 271183                source.Expression, Expression.Quote(lambda)));
 1184
 271185            return source.Provider.CreateQuery<TResult>(optimized);
 271186        }
 1187
 1188        /// <inheritdoc cref="Select(IQueryable, ParsingConfig, string, object[])"/>
 1189        public static IQueryable<TResult> Select<TResult>([NotNull] this IQueryable source, [NotNull] string selector, p
 271190        {
 271191            return Select<TResult>(source, null, selector, args);
 271192        }
 1193
 1194        /// <summary>
 1195        /// Projects each element of a sequence into a new class of type TResult.
 1196        /// Details see http://solutionizing.net/category/linq/
 1197        /// </summary>
 1198        /// <param name="source">A sequence of values to project.</param>
 1199        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1200        /// <param name="resultType">The result type.</param>
 1201        /// <param name="selector">A projection string expression to apply to each element.</param>
 1202        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1203        /// <returns>An <see cref="IQueryable{TResult}"/> whose elements are the result of invoking a projection string 
 1204        /// <example>
 1205        /// <code>
 1206        /// var users = queryable.Select(typeof(User), "new (Username, Pwd as Password)");
 1207        /// </code>
 1208        /// </example>
 1209        public static IQueryable Select([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] Ty
 31210        {
 31211            Check.NotNull(source, nameof(source));
 31212            Check.NotNull(resultType, nameof(resultType));
 31213            Check.NotEmpty(selector, nameof(selector));
 1214
 31215            bool createParameterCtor = source.IsLinqToObjects();
 31216            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1217
 31218            var optimized = OptimizeExpression(Expression.Call(
 31219                typeof(Queryable), nameof(Queryable.Select),
 31220                new[] { source.ElementType, resultType },
 31221                source.Expression, Expression.Quote(lambda)));
 1222
 31223            return source.Provider.CreateQuery(optimized);
 31224        }
 1225
 121226            foreach (DynamicOrdering dynamicOrdering in dynamicOrderings)
 31227            {
 31228                queryExpr = Expression.Call(
 31229                    typeof(Queryable), dynamicOrdering.MethodName,
 31230                    new[] { source.ElementType, dynamicOrdering.Selector.Type },
 31231                    queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)));
 31232            }
 1226        /// <inheritdoc cref="Select(IQueryable, ParsingConfig, Type, string, object[])"/>
 1227        public static IQueryable Select([NotNull] this IQueryable source, [NotNull] Type resultType, [NotNull] string se
 31228        {
 31229            return Select(source, null, resultType, selector, args);
 31230        }
 1231
 1232        #endregion Select
 1233
 21234            var optimized = OptimizeExpression(queryExpr);
 21235            return (IOrderedQueryable)source.Provider.CreateQuery(optimized);
 21236        }
 1237        #endregion OrderBy
 1238
 1239        #region Where
 1240        /// <summary>
 1241        /// Filters a sequence of values based on a predicate.
 1242        /// </summary>
 1243        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
 1244        /// <param name="source">A <see cref="IQueryable{TSource}"/> to filter.</param>
 1245        /// <param name="predicate">An expression string to test each element for a condition.</param>
 1246        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1247        /// <returns>A <see cref="IQueryable{TSource}"/> that contains elements from the input sequence that satisfy the
 1248        /// <example>
 1249        /// <code language="cs">
 1250        /// var result1 = queryable.Where("NumberProperty = 1");
 1251        /// var result2 = queryable.Where("NumberProperty = @0", 1);
 1252        /// var result3 = queryable.Where("StringProperty = null");
 1253        /// var result4 = queryable.Where("StringProperty = \"abc\"");
 1254        /// var result5 = queryable.Where("StringProperty = @0", "abc");
 1255        /// </code>
 1256        /// </example>
 1257        public static IQueryable<TSource> Where<TSource>([NotNull] this IQueryable<TSource> source, [NotNull] string pre
 1611258        {
 1611259            Check.NotNull(source, nameof(source));
 1611260            Check.NotEmpty(predicate, nameof(predicate));
 1234        #region SelectMany
 1235        /// <summary>
 1236        /// Projects each element of a sequence to an <see cref="IQueryable"/> and combines the resulting sequences into
 1237        /// </summary>
 1238        /// <param name="source">A sequence of values to project.</param>
 1239        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1240        /// <param name="selector">A projection string expression to apply to each element.</param>
 1241        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1242        /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a one-to-many projection func
 1243        /// <example>
 1244        /// <code>
 1245        /// var roles = users.SelectMany("Roles");
 1246        /// </code>
 1247        /// </example>
 1248        public static IQueryable SelectMany([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull
 131249        {
 131250            Check.NotNull(source, nameof(source));
 131251            Check.NotEmpty(selector, nameof(selector));
 1252
 131253            return SelectManyInternal(source, config, null, selector, args);
 111254        }
 1255
 1256        /// <inheritdoc cref="SelectMany(IQueryable, ParsingConfig, string, object[])"/>
 1257        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] string selector, params object[]
 131258        {
 131259            return SelectMany(source, (ParsingConfig)null, selector, args);
 111260        }
 1261
 1581262            return (IQueryable<TSource>)Where((IQueryable)source, predicate, args);
 1401263        }
 1264
 1265        /// <summary>
 1266        /// Filters a sequence of values based on a predicate.
 1267        /// </summary>
 1268        /// <param name="source">A <see cref="IQueryable"/> to filter.</param>
 1269        /// <param name="predicate">An expression string to test each element for a condition.</param>
 1270        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1271        /// <returns>A <see cref="IQueryable"/> that contains elements from the input sequence that satisfy the conditio
 1272        /// <example>
 1273        /// <code>
 1274        /// var result1 = queryable.Where("NumberProperty = 1");
 1275        /// var result2 = queryable.Where("NumberProperty = @0", 1);
 1276        /// var result3 = queryable.Where("StringProperty = null");
 1277        /// var result4 = queryable.Where("StringProperty = \"abc\"");
 1278        /// var result5 = queryable.Where("StringProperty = @0", "abc");
 1279        /// </code>
 1280        /// </example>
 1281        public static IQueryable Where([NotNull] this IQueryable source, [NotNull] string predicate, params object[] arg
 1621282        {
 1621283            Check.NotNull(source, nameof(source));
 1611284            Check.NotEmpty(predicate, nameof(predicate));
 1285
 1611286            bool createParameterCtor = source.IsLinqToObjects();
 1611287            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, typeo
 1288
 1431289            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), "Where", new[] { source.ElementType },
 1431290            return source.Provider.CreateQuery(optimized);
 1431291        }
 1292        #endregion
 1293
 1294        #region Private Helpers
 1295        // Code below is based on https://github.com/aspnet/EntityFramework/blob/9186d0b78a3176587eeb0f557c331f635760fe9
 1296
 1297        private static IQueryable CreateQuery(MethodInfo operatorMethodInfo, IQueryable source)
 01298        {
 01299             if (operatorMethodInfo.IsGenericMethod)
 01300            {
 01301                operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 01302            }
 1303
 01304            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 01305            return source.Provider.CreateQuery(optimized);
 01306        }
 1307
 1308        private static IQueryable CreateQuery(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression express
 41309            => CreateQuery(operatorMethodInfo, source, Expression.Quote(expression));
 1310
 1311        private static IQueryable CreateQuery(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
 251312        {
 251313            operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
 251314                    ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(object))
 251315                    : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 1316
 251317            return source.Provider.CreateQuery(Expression.Call(null, operatorMethodInfo, new[] { source.Expression, expr
 251318        }
 1262        /// <summary>
 1263        /// Projects each element of a sequence to an <see cref="IQueryable"/> and combines the resulting sequences into
 1264        /// </summary>
 1265        /// <param name="source">A sequence of values to project.</param>
 1266        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1267        /// <param name="selector">A projection string expression to apply to each element.</param>
 1268        /// <param name="resultType">The result type.</param>
 1269        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1270        /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a one-to-many projection func
 1271        /// <example>
 1272        /// <code>
 1273        /// var permissions = users.SelectMany(typeof(Permission), "Roles.SelectMany(Permissions)");
 1274        /// </code>
 1275        /// </example>
 1276        public static IQueryable SelectMany([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull
 21277        {
 21278            Check.NotNull(source, nameof(source));
 21279            Check.NotNull(resultType, nameof(resultType));
 21280            Check.NotEmpty(selector, nameof(selector));
 1281
 21282            return SelectManyInternal(source, config, resultType, selector, args);
 21283        }
 1284
 1285        /// <inheritdoc cref="SelectMany(IQueryable, ParsingConfig, Type, string, object[])"/>
 1286        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] Type resultType, [NotNull] strin
 21287        {
 21288            return SelectMany(source, null, resultType, selector, args);
 21289        }
 1290
 1291        private static IQueryable SelectManyInternal(IQueryable source, ParsingConfig config, Type resultType, string se
 151292        {
 151293            bool createParameterCtor = source.IsLinqToObjects();
 151294            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1295
 1296            //Extra help to get SelectMany to work from StackOverflow Answer
 1297            //http://stackoverflow.com/a/3001674/2465182
 1298
 1299            // if resultType is not specified, create one based on the lambda.Body.Type
 131300             if (resultType == null)
 111301            {
 1302                // SelectMany assumes that lambda.Body.Type is a generic type and throws an exception on
 1303                // lambda.Body.Type.GetGenericArguments()[0] when used over an array as GetGenericArguments() returns an
 111304                 if (lambda.Body.Type.IsArray)
 61305                {
 61306                    resultType = lambda.Body.Type.GetElementType();
 61307                }
 1308                else
 51309                {
 51310                    resultType = lambda.Body.Type.GetGenericArguments()[0];
 51311                }
 111312            }
 1313
 1314            //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is.
 131315            Type enumerableType = typeof(IEnumerable<>).MakeGenericType(resultType);
 131316            Type inputType = source.Expression.Type.GetTypeInfo().GetGenericTypeArguments()[0];
 131317            Type delegateType = typeof(Func<,>).MakeGenericType(inputType, enumerableType);
 131318            lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters);
 1319
 1320        private static object Execute(MethodInfo operatorMethodInfo, IQueryable source)
 181321        {
 181322             if (operatorMethodInfo.IsGenericMethod)
 181323            {
 181324                operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 181325            }
 1326
 181327            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 181328            return source.Provider.Execute(optimized);
 181329        }
 1330
 1331        private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source)
 421332        {
 421333             if (operatorMethodInfo.IsGenericMethod)
 421334            {
 421335                operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 421336            }
 1337
 421338            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 421339            return source.Provider.Execute<TResult>(optimized);
 421340        }
 1341
 1342        private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression)
 41343            => Execute(operatorMethodInfo, source, Expression.Quote(expression));
 1344
 1345        private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
 41346        {
 41347            operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
 41348                    ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(object))
 41349                    : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 1350
 41351            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, new[] { source.Expression, expr
 41352            return source.Provider.Execute(optimized);
 41353        }
 1354
 1355        private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expre
 71356            => Execute<TResult>(operatorMethodInfo, source, Expression.Quote(expression));
 1357
 1358        private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
 71359        {
 71360            operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
 71361                    ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(TResult))
 71362                    : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 1363
 71364            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, new[] { source.Expression, expr
 71365            return source.Provider.Execute<TResult>(optimized);
 71366        }
 131320            var optimized = OptimizeExpression(Expression.Call(
 131321                typeof(Queryable), nameof(Queryable.SelectMany),
 131322                new[] { source.ElementType, resultType },
 131323                source.Expression, Expression.Quote(lambda))
 131324            );
 1325
 131326            return source.Provider.CreateQuery(optimized);
 131327        }
 1328
 1329        /// <summary>
 1330        /// Projects each element of a sequence to an <see cref="IQueryable{TResult}"/> and combines the resulting seque
 1331        /// </summary>
 1332        /// <typeparam name="TResult">The type of the result.</typeparam>
 1333        /// <param name="source">A sequence of values to project.</param>
 1334        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1335        /// <param name="selector">A projection string expression to apply to each element.</param>
 1336        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1337        /// <returns>An <see cref="IQueryable{TResult}"/> whose elements are the result of invoking a one-to-many projec
 1338        /// <example>
 1339        /// <code>
 1340        /// <![CDATA[
 1341        /// var permissions = users.SelectMany<Permission>("Roles.SelectMany(Permissions)");
 1342        /// ]]>
 1343        /// </code>
 1344        /// </example>
 1345        public static IQueryable<TResult> SelectMany<TResult>([NotNull] this IQueryable source, [CanBeNull] ParsingConfi
 21346        {
 21347            Check.NotNull(source, nameof(source));
 21348            Check.NotEmpty(selector, nameof(selector));
 1349
 21350            bool createParameterCtor = source.IsLinqToObjects();
 21351            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null,
 1352
 1353            //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is.
 21354            Type inputType = source.Expression.Type.GetTypeInfo().GetGenericTypeArguments()[0];
 21355            Type enumerableType = typeof(IEnumerable<>).MakeGenericType(typeof(TResult));
 21356            Type delegateType = typeof(Func<,>).MakeGenericType(inputType, enumerableType);
 21357            lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters);
 1358
 21359            var optimized = OptimizeExpression(Expression.Call(
 21360                typeof(Queryable), nameof(Queryable.SelectMany),
 21361                new[] { source.ElementType, typeof(TResult) },
 21362                source.Expression, Expression.Quote(lambda))
 21363            );
 1364
 21365            return source.Provider.CreateQuery<TResult>(optimized);
 21366        }
 1367
 1368        private static MethodInfo GetMethod<TResult>(string name, int parameterCount = 0, Func<MethodInfo, bool> predica
 01369            GetMethod(name, parameterCount, mi => (mi.ReturnType == typeof(TResult)) && ((predicate == null) || predicat
 1370
 1371        private static MethodInfo GetMethod(string name, int parameterCount = 0, Func<MethodInfo, bool> predicate = null
 431372            typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => (mi.GetParameters().Length == paramete
 1373        #endregion Private Helpers
 1374    }
 1375}
 1368        /// <inheritdoc cref="SelectMany(IQueryable, ParsingConfig, string, object[])"/>
 1369        public static IQueryable<TResult> SelectMany<TResult>([NotNull] this IQueryable source, [NotNull] string selecto
 21370        {
 21371            return SelectMany<TResult>(source, null, selector, args);
 21372        }
 1373
 1374        /// <summary>
 1375        /// Projects each element of a sequence to an <see cref="IQueryable"/>
 1376        /// and invokes a result selector function on each element therein. The resulting
 1377        /// values from each intermediate sequence are combined into a single, one-dimensional
 1378        /// sequence and returned.
 1379        /// </summary>
 1380        /// <param name="source">A sequence of values to project.</param>
 1381        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1382        /// <param name="collectionSelector">A projection function to apply to each element of the input sequence.</para
 1383        /// <param name="resultSelector">A projection function to apply to each element of each intermediate sequence. S
 1384        /// <param name="collectionSelectorArgs">An object array that contains zero or more objects to insert into the p
 1385        /// <param name="resultSelectorArgs">An object array that contains zero or more objects to insert into the predi
 1386        /// <returns>
 1387        /// An <see cref="IQueryable"/> whose elements are the result of invoking the one-to-many
 1388        /// projection function <paramref name="collectionSelector"/> on each element of source and then mapping
 1389        /// each of those sequence elements and their corresponding source element to a result element.
 1390        /// </returns>
 1391        /// <example>
 1392        /// <code>
 1393        /// <![CDATA[
 1394        /// // TODO
 1395        /// ]]>
 1396        /// </code>
 1397        /// </example>
 1398        public static IQueryable SelectMany([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull
 01399        {
 01400            return SelectMany(source, collectionSelector, resultSelector, "x", "y", collectionSelectorArgs, resultSelect
 01401        }
 1402
 1403        /// <inheritdoc cref="SelectMany(IQueryable, ParsingConfig, string, object[])"/>
 1404        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] string collectionSelector, [NotN
 11405        {
 11406            return SelectMany(source, null, collectionSelector, resultSelector, "x", "y", collectionSelectorArgs, result
 11407        }
 1408
 1409        /// <summary>
 1410        /// Projects each element of a sequence to an <see cref="IQueryable"/>
 1411        /// and invokes a result selector function on each element therein. The resulting
 1412        /// values from each intermediate sequence are combined into a single, one-dimensional
 1413        /// sequence and returned.
 1414        /// </summary>
 1415        /// <param name="source">A sequence of values to project.</param>
 1416        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1417        /// <param name="collectionSelector">A projection function to apply to each element of the input sequence.</para
 1418        /// <param name="collectionParameterName">The name from collectionParameter to use. Default is x.</param>
 1419        /// <param name="resultSelector">A projection function to apply to each element of each intermediate sequence.</
 1420        /// <param name="resultParameterName">The name from resultParameterName to use. Default is y.</param>
 1421        /// <param name="collectionSelectorArgs">An object array that contains zero or more objects to insert into the p
 1422        /// <param name="resultSelectorArgs">An object array that contains zero or more objects to insert into the predi
 1423        /// <returns>
 1424        /// An <see cref="IQueryable"/> whose elements are the result of invoking the one-to-many
 1425        /// projection function <paramref name="collectionSelector"/> on each element of source and then mapping
 1426        /// each of those sequence elements and their corresponding source element to a result element.
 1427        /// </returns>
 1428        /// <example>
 1429        /// <code>
 1430        /// <![CDATA[
 1431        /// // TODO
 1432        /// ]]>
 1433        /// </code>
 1434        /// </example>
 1435        public static IQueryable SelectMany([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull
 21436        {
 21437            Check.NotNull(source, nameof(source));
 21438            Check.NotEmpty(collectionSelector, nameof(collectionSelector));
 21439            Check.NotEmpty(collectionParameterName, nameof(collectionParameterName));
 21440            Check.NotEmpty(resultSelector, nameof(resultSelector));
 21441            Check.NotEmpty(resultParameterName, nameof(resultParameterName));
 1442
 21443            bool createParameterCtor = source.IsLinqToObjects();
 21444            LambdaExpression sourceSelectLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, sourc
 1445
 1446            //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is.
 21447            Type sourceLambdaInputType = source.Expression.Type.GetGenericArguments()[0];
 21448            Type sourceLambdaResultType = sourceSelectLambda.Body.Type.GetGenericArguments()[0];
 21449            Type sourceLambdaEnumerableType = typeof(IEnumerable<>).MakeGenericType(sourceLambdaResultType);
 21450            Type sourceLambdaDelegateType = typeof(Func<,>).MakeGenericType(sourceLambdaInputType, sourceLambdaEnumerabl
 1451
 21452            sourceSelectLambda = Expression.Lambda(sourceLambdaDelegateType, sourceSelectLambda.Body, sourceSelectLambda
 1453
 1454            //we have to create additional lambda for result selection
 21455            ParameterExpression xParameter = ParameterExpressionHelper.CreateParameterExpression(source.ElementType, col
 21456            ParameterExpression yParameter = ParameterExpressionHelper.CreateParameterExpression(sourceLambdaResultType,
 1457
 21458            LambdaExpression resultSelectLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, new[]
 21459            Type resultLambdaResultType = resultSelectLambda.Body.Type;
 1460
 21461            var optimized = OptimizeExpression(Expression.Call(
 21462                typeof(Queryable), nameof(Queryable.SelectMany),
 21463                new[] { source.ElementType, sourceLambdaResultType, resultLambdaResultType },
 21464                source.Expression, Expression.Quote(sourceSelectLambda), Expression.Quote(resultSelectLambda))
 21465            );
 1466
 21467            return source.Provider.CreateQuery(optimized);
 21468        }
 1469
 1470        /// <inheritdoc cref="SelectMany(IQueryable, ParsingConfig, string, string, string, string, object[], object[])"
 1471        public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] string collectionSelector, [NotN
 11472        {
 11473            return SelectMany(source, null, collectionSelector, resultSelector, collectionParameterName, resultParameter
 11474        }
 1475
 1476        #endregion SelectMany
 1477
 1478        #region Single/SingleOrDefault
 1479        /// <summary>
 1480        /// Returns the only element of a sequence, and throws an exception if there
 1481        /// is not exactly one element in the sequence.
 1482        /// </summary>
 1483        /// <param name="source">A <see cref="IQueryable"/> to return the single element of.</param>
 1484        /// <returns>The single element of the input sequence.</returns>
 1485#if NET35
 1486        public static object Single([NotNull] this IQueryable source)
 1487#else
 1488        public static dynamic Single([NotNull] this IQueryable source)
 1489#endif
 581490        {
 581491            Check.NotNull(source, nameof(source));
 1492
 581493            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), nameof(Queryable.Single), new[] { sour
 581494            return source.Provider.Execute(optimized);
 581495        }
 1496
 11497        private static readonly MethodInfo _singlePredicate = GetMethod(nameof(Queryable.Single), 1);
 1498
 1499        /// <summary>
 1500        /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if ther
 1501        /// is not exactly one element in the sequence.
 1502        /// </summary>
 1503        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 1504        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1505        /// <param name="predicate">A function to test each element for a condition.</param>
 1506        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1507        /// <returns>The first element in source that passes the test in predicate.</returns>
 1508#if NET35
 1509        public static object Single([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string
 1510#else
 1511        public static dynamic Single([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] strin
 1512#endif
 21513        {
 21514            Check.NotNull(source, nameof(source));
 21515            Check.NotEmpty(predicate, nameof(predicate));
 1516
 21517            bool createParameterCtor = source.IsLinqToObjects();
 21518            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1519
 21520            return Execute(_singlePredicate, source, lambda);
 21521        }
 1522
 1523        /// <inheritdoc cref="Single(IQueryable, ParsingConfig, string, object[])"/>
 1524#if NET35
 1525        public static object Single([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 1526#else
 1527        public static dynamic Single([NotNull] this IQueryable source, [NotNull] string predicate, params object[] args)
 1528#endif
 11529        {
 11530            return Single(source, null, predicate, args);
 11531        }
 1532
 1533        /// <summary>
 1534        /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if ther
 1535        /// is not exactly one element in the sequence.
 1536        /// </summary>
 1537        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 1538        /// <param name="lambda">A cached Lambda Expression.</param>
 1539        /// <returns>The first element in source that passes the test in predicate.</returns>
 1540#if NET35
 1541        public static object Single([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 1542#else
 1543        public static dynamic Single([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 1544#endif
 11545        {
 11546            Check.NotNull(source, nameof(source));
 11547            return Execute(_singlePredicate, source, lambda);
 11548        }
 1549
 1550        /// <summary>
 1551        /// Returns the only element of a sequence, or a default value if the sequence
 1552        /// is empty; this method throws an exception if there is more than one element
 1553        /// in the sequence.
 1554        /// </summary>
 1555        /// <param name="source">A <see cref="IQueryable"/> to return the single element of.</param>
 1556        /// <returns>The single element of the input sequence, or default if the sequence contains no elements.</returns
 1557#if NET35
 1558        public static object SingleOrDefault([NotNull] this IQueryable source)
 1559#else
 1560        public static dynamic SingleOrDefault([NotNull] this IQueryable source)
 1561#endif
 21562        {
 21563            Check.NotNull(source, nameof(source));
 1564
 21565            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), nameof(Queryable.SingleOrDefault), new
 21566            return source.Provider.Execute(optimized);
 21567        }
 1568
 11569        private static readonly MethodInfo _singleDefaultPredicate = GetMethod(nameof(Queryable.SingleOrDefault), 1);
 1570
 1571        /// <summary>
 1572        /// Returns the only element of a sequence that satisfies a specified condition or a default value if the sequen
 1573        /// is empty; and throws an exception if there is not exactly one element in the sequence.
 1574        /// </summary>
 1575        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 1576        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1577        /// <param name="predicate">A function to test each element for a condition.</param>
 1578        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1579        /// <returns>The first element in source that passes the test in predicate.</returns>
 1580#if NET35
 1581        public static object SingleOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNul
 1582#else
 1583        public static dynamic SingleOrDefault([NotNull] this IQueryable source,  [CanBeNull] ParsingConfig config, [NotN
 1584#endif
 21585        {
 21586            Check.NotNull(source, nameof(source));
 21587            Check.NotEmpty(predicate, nameof(predicate));
 1588
 21589            bool createParameterCtor = source.IsLinqToObjects();
 21590            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1591
 21592            return Execute(_singleDefaultPredicate, source, lambda);
 21593        }
 1594
 1595        /// <inheritdoc cref="SingleOrDefault(IQueryable, ParsingConfig, string, object[])"/>
 1596#if NET35
 1597        public static object SingleOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params object
 1598#else
 1599        public static dynamic SingleOrDefault([NotNull] this IQueryable source, [NotNull] string predicate, params objec
 1600#endif
 11601        {
 11602            return SingleOrDefault(source, null, predicate, args);
 11603        }
 1604
 1605        /// <summary>
 1606        /// Returns the only element of a sequence that satisfies a specified condition or a default value if the sequen
 1607        /// is empty; and throws an exception if there is not exactly one element in the sequence.
 1608        /// </summary>
 1609        /// <param name="source">The <see cref="IQueryable"/> to return the last element of.</param>
 1610        /// <param name="lambda">A cached Lambda Expression.</param>
 1611        /// <returns>The first element in source that passes the test in predicate.</returns>
 1612#if NET35
 1613        public static object SingleOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 1614#else
 1615        public static dynamic SingleOrDefault([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 1616#endif
 11617        {
 11618            Check.NotNull(source, nameof(source));
 11619            return Execute(_singleDefaultPredicate, source, lambda);
 11620        }
 1621        #endregion Single/SingleOrDefault
 1622
 1623        #region Skip
 11624        private static readonly MethodInfo _skip = GetMethod(nameof(Queryable.Skip), 1);
 1625
 1626        /// <summary>
 1627        /// Bypasses a specified number of elements in a sequence and then returns the remaining elements.
 1628        /// </summary>
 1629        /// <param name="source">A <see cref="IQueryable"/> to return elements from.</param>
 1630        /// <param name="count">The number of elements to skip before returning the remaining elements.</param>
 1631        /// <returns>A <see cref="IQueryable"/> that contains elements that occur after the specified index in the input
 1632        public static IQueryable Skip([NotNull] this IQueryable source, int count)
 101633        {
 101634            Check.NotNull(source, nameof(source));
 201635            Check.Condition(count, x => x >= 0, nameof(count));
 1636
 1637            //no need to skip if count is zero
 101638             if (count == 0)
 11639                return source;
 1640
 91641            return CreateQuery(_skip, source, Expression.Constant(count));
 101642        }
 1643        #endregion Skip
 1644
 1645        #region SkipWhile
 1646
 11647        private static readonly MethodInfo _skipWhilePredicate = GetMethod(nameof(Queryable.SkipWhile), 1, mi =>
 31648        {
 31649            return mi.GetParameters().Length == 2 &&
 31650                   mi.GetParameters()[1].ParameterType.GetTypeInfo().IsGenericType &&
 31651                   mi.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>) &&
 31652                   mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetTypeInfo().IsGenericType &&
 31653                   mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Fun
 31654        });
 1655
 1656        /// <summary>
 1657        /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elem
 1658        /// </summary>
 1659        /// <param name="source">A sequence to check for being empty.</param>
 1660        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1661        /// <param name="predicate">A function to test each element for a condition.</param>
 1662        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1663        /// <example>
 1664        /// <code language="cs">
 1665        /// IQueryable queryable = employees.AsQueryable();
 1666        /// var result1 = queryable.SkipWhile("Income > 50");
 1667        /// var result2 = queryable.SkipWhile("Income > @0", 50);
 1668        /// </code>
 1669        /// </example>
 1670        /// <returns>An <see cref="IQueryable"/> that contains elements from source starting at the first element in the
 1671        public static IQueryable SkipWhile([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull]
 31672        {
 31673            Check.NotNull(source, nameof(source));
 31674            Check.NotNull(predicate, nameof(predicate));
 1675
 31676            bool createParameterCtor = source.IsLinqToObjects();
 31677            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1678
 31679            return CreateQuery(_skipWhilePredicate, source, lambda);
 31680        }
 1681
 1682        /// <inheritdoc cref="SkipWhile(IQueryable, ParsingConfig, string, object[])"/>
 1683        public static IQueryable SkipWhile([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] par
 21684        {
 21685            return SkipWhile(source, null, predicate, args);
 21686        }
 1687
 1688        #endregion SkipWhile
 1689
 1690        #region Sum
 1691        /// <summary>
 1692        /// Computes the sum of a sequence of numeric values.
 1693        /// </summary>
 1694        /// <param name="source">A sequence of numeric values to calculate the sum of.</param>
 1695        /// <returns>The sum of the values in the sequence.</returns>
 1696        public static object Sum([NotNull] this IQueryable source)
 21697        {
 21698            Check.NotNull(source, nameof(source));
 1699
 21700            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), nameof(Queryable.Sum), null, source.Ex
 21701            return source.Provider.Execute(optimized);
 21702        }
 1703        #endregion Sum
 1704
 1705        #region Take
 11706        private static readonly MethodInfo _take = GetMethod(nameof(Queryable.Take), 1);
 1707        /// <summary>
 1708        /// Returns a specified number of contiguous elements from the start of a sequence.
 1709        /// </summary>
 1710        /// <param name="source">The sequence to return elements from.</param>
 1711        /// <param name="count">The number of elements to return.</param>
 1712        /// <returns>A <see cref="IQueryable"/> that contains the specified number of elements from the start of source.
 1713        public static IQueryable Take([NotNull] this IQueryable source, int count)
 141714        {
 141715            Check.NotNull(source, nameof(source));
 281716            Check.Condition(count, x => x >= 0, nameof(count));
 1717
 141718            return CreateQuery(_take, source, Expression.Constant(count));
 141719        }
 1720        #endregion Take
 1721
 1722        #region TakeWhile
 1723
 11724        private static readonly MethodInfo _takeWhilePredicate = GetMethod(nameof(Queryable.TakeWhile), 1, mi =>
 31725        {
 31726            return mi.GetParameters().Length == 2 &&
 31727                   mi.GetParameters()[1].ParameterType.GetTypeInfo().IsGenericType &&
 31728                   mi.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>) &&
 31729                   mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetTypeInfo().IsGenericType &&
 31730                   mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Fun
 31731        });
 1732
 1733        /// <summary>
 1734        /// Returns elements from a sequence as long as a specified condition is true.
 1735        /// </summary>
 1736        /// <param name="source">A sequence to check for being empty.</param>
 1737        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1738        /// <param name="predicate">A function to test each element for a condition.</param>
 1739        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1740        /// <example>
 1741        /// <code language="cs">
 1742        /// IQueryable queryable = employees.AsQueryable();
 1743        /// var result1 = queryable.TakeWhile("Income > 50");
 1744        /// var result2 = queryable.TakeWhile("Income > @0", 50);
 1745        /// </code>
 1746        /// </example>
 1747        /// <returns>An <see cref="IQueryable"/> that contains elements from the input sequence occurring before the ele
 1748        public static IQueryable TakeWhile([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull]
 31749        {
 31750            Check.NotNull(source, nameof(source));
 31751            Check.NotNull(predicate, nameof(predicate));
 1752
 31753            bool createParameterCtor = source.IsLinqToObjects();
 31754            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1755
 31756            return CreateQuery(_takeWhilePredicate, source, lambda);
 31757        }
 1758
 1759        /// <inheritdoc cref="TakeWhile(IQueryable, ParsingConfig, string, object[])"/>
 1760        public static IQueryable TakeWhile([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] par
 21761        {
 21762            return TakeWhile(source, null, predicate, args);
 21763        }
 1764
 1765        #endregion TakeWhile
 1766
 1767        #region ThenBy
 1768        /// <summary>
 1769        /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
 1770        /// </summary>
 1771        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
 1772        /// <param name="source">A sequence of values to order.</param>
 1773        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1774        /// <param name="ordering">An expression string to indicate values to order by.</param>
 1775        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1776        /// <returns>A <see cref="IOrderedQueryable{T}"/> whose elements are sorted according to the specified <paramref
 1777        /// <example>
 1778        /// <code>
 1779        /// <![CDATA[
 1780        /// var result = queryable.OrderBy<User>("LastName");
 1781        /// var resultSingle = result.ThenBy<User>("NumberProperty");
 1782        /// var resultSingleDescending = result.ThenBy<User>("NumberProperty DESC");
 1783        /// var resultMultiple = result.ThenBy<User>("NumberProperty, StringProperty");
 1784        /// ]]>
 1785        /// </code>
 1786        /// </example>
 1787        public static IOrderedQueryable<TSource> ThenBy<TSource>([NotNull] this IOrderedQueryable<TSource> source, [CanB
 61788        {
 61789            return (IOrderedQueryable<TSource>)ThenBy((IOrderedQueryable)source, config, ordering, args);
 21790        }
 1791
 1792        /// <inheritdoc cref="ThenBy{TSource}(IOrderedQueryable{TSource}, ParsingConfig, string, object[])"/>
 1793        public static IOrderedQueryable<TSource> ThenBy<TSource>([NotNull] this IOrderedQueryable<TSource> source, [NotN
 61794        {
 61795            return ThenBy(source, null, ordering, args);
 21796        }
 1797        /// <summary>
 1798        /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
 1799        /// </summary>
 1800        /// <param name="source">A sequence of values to order.</param>
 1801        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1802        /// <param name="ordering">An expression string to indicate values to order by.</param>
 1803        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1804        /// <returns>A <see cref="IQueryable"/> whose elements are sorted according to the specified <paramref name="ord
 1805        /// <example>
 1806        /// <code>
 1807        /// var result = queryable.OrderBy("LastName");
 1808        /// var resultSingle = result.OrderBy("NumberProperty");
 1809        /// var resultSingleDescending = result.OrderBy("NumberProperty DESC");
 1810        /// var resultMultiple = result.OrderBy("NumberProperty, StringProperty DESC");
 1811        /// </code>
 1812        /// </example>
 1813        public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source, [CanBeNull] ParsingConfig config
 71814        {
 71815            Check.NotNull(source, nameof(source));
 61816            Check.NotEmpty(ordering, nameof(ordering));
 1817
 31818            ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(source.ElementType,
 31819            ExpressionParser parser = new ExpressionParser(parameters, ordering, args, config);
 31820            IList<DynamicOrdering> dynamicOrderings = parser.ParseOrdering(forceThenBy: true);
 1821
 21822            Expression queryExpr = source.Expression;
 1823
 121824            foreach (DynamicOrdering dynamicOrdering in dynamicOrderings)
 31825            {
 31826                queryExpr = Expression.Call(
 31827                    typeof(Queryable), dynamicOrdering.MethodName,
 31828                    new[] { source.ElementType, dynamicOrdering.Selector.Type },
 31829                    queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)));
 31830            }
 1831
 21832            var optimized = OptimizeExpression(queryExpr);
 21833            return (IOrderedQueryable)source.Provider.CreateQuery(optimized);
 21834        }
 1835
 1836        /// <inheritdoc cref="ThenBy(IOrderedQueryable, ParsingConfig, string, object[])"/>
 1837        public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source, [NotNull] string ordering, param
 11838        {
 11839            return ThenBy(source, null, ordering, args);
 01840        }
 1841
 1842        #endregion OrderBy
 1843
 1844        #region Where
 1845        /// <summary>
 1846        /// Filters a sequence of values based on a predicate.
 1847        /// </summary>
 1848        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
 1849        /// <param name="source">A <see cref="IQueryable{TSource}"/> to filter.</param>
 1850        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1851        /// <param name="predicate">An expression string to test each element for a condition.</param>
 1852        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1853        /// <returns>A <see cref="IQueryable{TSource}"/> that contains elements from the input sequence that satisfy the
 1854        /// <example>
 1855        /// <code language="cs">
 1856        /// var result1 = queryable.Where("NumberProperty = 1");
 1857        /// var result2 = queryable.Where("NumberProperty = @0", 1);
 1858        /// var result3 = queryable.Where("StringProperty = null");
 1859        /// var result4 = queryable.Where("StringProperty = \"abc\"");
 1860        /// var result5 = queryable.Where("StringProperty = @0", "abc");
 1861        /// </code>
 1862        /// </example>
 1863        public static IQueryable<TSource> Where<TSource>([NotNull] this IQueryable<TSource> source, [CanBeNull] ParsingC
 1691864        {
 1691865            Check.NotNull(source, nameof(source));
 1691866            Check.NotEmpty(predicate, nameof(predicate));
 1867
 1661868            return (IQueryable<TSource>)Where((IQueryable)source, config, predicate, args);
 1501869        }
 1870
 1871        /// <inheritdoc cref="DynamicQueryableExtensions.Where{TSource}(IQueryable{TSource}, ParsingConfig, string, obje
 1872        public static IQueryable<TSource> Where<TSource>([NotNull] this IQueryable<TSource> source, [NotNull] string pre
 1431873        {
 1431874            return Where(source, null, predicate, args);
 1241875        }
 1876
 1877        /// <summary>
 1878        /// Filters a sequence of values based on a predicate.
 1879        /// </summary>
 1880        /// <param name="source">A <see cref="IQueryable"/> to filter.</param>
 1881        /// <param name="config">The <see cref="ParsingConfig"/>.</param>
 1882        /// <param name="predicate">An expression string to test each element for a condition.</param>
 1883        /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parame
 1884        /// <returns>A <see cref="IQueryable"/> that contains elements from the input sequence that satisfy the conditio
 1885        /// <example>
 1886        /// <code>
 1887        /// var result1 = queryable.Where("NumberProperty = 1");
 1888        /// var result2 = queryable.Where("NumberProperty = @0", 1);
 1889        /// var result3 = queryable.Where("StringProperty = null");
 1890        /// var result4 = queryable.Where("StringProperty = \"abc\"");
 1891        /// var result5 = queryable.Where("StringProperty = @0", "abc");
 1892        /// </code>
 1893        /// </example>
 1894        public static IQueryable Where([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] str
 1701895        {
 1701896            Check.NotNull(source, nameof(source));
 1691897            Check.NotEmpty(predicate, nameof(predicate));
 1898
 1691899            bool createParameterCtor = source.IsLinqToObjects();
 1691900            LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementTyp
 1901
 1541902            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), nameof(Queryable.Where), new[] { sourc
 1531903            return source.Provider.CreateQuery(optimized);
 1531904        }
 1905
 1906        /// <inheritdoc cref="DynamicQueryableExtensions.Where(IQueryable, ParsingConfig, string, object[])"/>
 1907        public static IQueryable Where([NotNull] this IQueryable source, [NotNull] string predicate, params object[] arg
 41908        {
 41909            return Where(source, null, predicate, args);
 31910        }
 1911
 1912        /// <summary>
 1913        /// Filters a sequence of values based on a predicate.
 1914        /// </summary>
 1915        /// <param name="source">A <see cref="IQueryable"/> to filter.</param>
 1916        /// <param name="lambda">A cached Lambda Expression.</param>
 1917        public static IQueryable Where([NotNull] this IQueryable source, [NotNull] LambdaExpression lambda)
 11918        {
 11919            Check.NotNull(source, nameof(source));
 11920            Check.NotNull(lambda, nameof(lambda));
 1921
 11922            var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), nameof(Queryable.Where), new[] { sourc
 11923            return source.Provider.CreateQuery(optimized);
 11924        }
 1925        #endregion
 1926
 1927        #region Private Helpers
 1928        private static void CheckOuterAndInnerTypes(bool createParameterCtor, Type outerType, Type innerType, string out
 101929        {
 101930            Type outerSelectorReturnType = outerSelectorLambda.Body.Type;
 101931            Type innerSelectorReturnType = innerSelectorLambda.Body.Type;
 1932
 1933            // If types are not the same, try to convert to Nullable and generate new LambdaExpression
 101934             if (outerSelectorReturnType != innerSelectorReturnType)
 61935            {
 1936                //var outerSelectorReturnTypeInfo = outerSelectorReturnType.GetTypeInfo();
 1937                //var innerSelectorReturnTypeInfo = innerSelectorReturnType.GetTypeInfo();
 1938                //if (outerSelectorReturnTypeInfo.BaseType == typeof(DynamicClass) && innerSelectorReturnTypeInfo.BaseTy
 1939                //{
 1940
 1941                //}
 1942
 61943                 if (TypeHelper.IsNullableType(outerSelectorReturnType) && !TypeHelper.IsNullableType(innerSelectorReturn
 21944                {
 21945                    innerSelectorReturnType = ExpressionParser.ToNullableType(innerSelectorReturnType);
 21946                    innerSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, innerType, innerSelec
 21947                }
 41948                 else if (!TypeHelper.IsNullableType(outerSelectorReturnType) && TypeHelper.IsNullableType(innerSelectorR
 21949                {
 21950                    outerSelectorReturnType = ExpressionParser.ToNullableType(outerSelectorReturnType);
 21951                    outerSelectorLambda = DynamicExpressionParser.ParseLambda(createParameterCtor, outerType, outerSelec
 21952                }
 1953
 1954                // If types are still not the same, throw an Exception
 61955                 if (outerSelectorReturnType != innerSelectorReturnType)
 21956                {
 21957                    throw new ParseException(string.Format(CultureInfo.CurrentCulture, Res.IncompatibleTypes, outerSelec
 1958                }
 41959            }
 81960        }
 1961
 1962        // Code below is based on https://github.com/aspnet/EntityFramework/blob/9186d0b78a3176587eeb0f557c331f635760fe9
 1963        private static IQueryable CreateQuery(MethodInfo operatorMethodInfo, IQueryable source)
 61964        {
 61965             if (operatorMethodInfo.IsGenericMethod)
 61966            {
 61967                operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 61968            }
 1969
 61970            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 61971            return source.Provider.CreateQuery(optimized);
 61972        }
 1973
 1974        private static IQueryable CreateQuery(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression express
 61975            => CreateQuery(operatorMethodInfo, source, Expression.Quote(expression));
 1976
 1977        private static IQueryable CreateQuery(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
 331978        {
 331979            operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
 331980                    ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(object))
 331981                    : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 1982
 331983            return source.Provider.CreateQuery(Expression.Call(null, operatorMethodInfo, source.Expression, expression))
 331984        }
 1985
 1986        private static object Execute(MethodInfo operatorMethodInfo, IQueryable source)
 321987        {
 321988             if (operatorMethodInfo.IsGenericMethod)
 321989            {
 321990                operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 321991            }
 1992
 321993            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 321994            return source.Provider.Execute(optimized);
 321995        }
 1996
 1997        private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source)
 431998        {
 431999             if (operatorMethodInfo.IsGenericMethod)
 432000            {
 432001                operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(source.ElementType);
 432002            }
 2003
 432004            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression));
 432005            return source.Provider.Execute<TResult>(optimized);
 432006        }
 2007
 2008        private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression)
 582009            => Execute(operatorMethodInfo, source, Expression.Quote(expression));
 2010
 2011        private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
 582012        {
 582013            operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
 582014                    ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(object))
 582015                    : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 2016
 582017            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression, expression))
 582018            return source.Provider.Execute(optimized);
 582019        }
 2020
 2021        private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expre
 102022            => Execute<TResult>(operatorMethodInfo, source, Expression.Quote(expression));
 2023
 2024        private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
 102025        {
 102026            operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
 102027                    ? operatorMethodInfo.MakeGenericMethod(source.ElementType, typeof(TResult))
 102028                    : operatorMethodInfo.MakeGenericMethod(source.ElementType);
 2029
 102030            var optimized = OptimizeExpression(Expression.Call(null, operatorMethodInfo, source.Expression, expression))
 102031            return source.Provider.Execute<TResult>(optimized);
 102032        }
 2033
 2034        private static MethodInfo GetMethod(string name, int parameterCount = 0, Func<MethodInfo, bool> predicate = null
 212035        {
 2036            try
 212037            {
 212038                return typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi =>
 612039                    mi.GetParameters().Length == parameterCount + 1 && (predicate == null || predicate(mi)));
 2040            }
 02041            catch (Exception ex)
 02042            {
 02043                throw new Exception("Method not found: " + name, ex);
 2044            }
 212045        }
 2046        #endregion Private Helpers
 2047    }
 2048}
-
+

Methods/Properties

-.cctor()
-OptimizeExpression(System.Linq.Expressions.Expression)
-Any(System.Linq.IQueryable)
-Any(System.Linq.IQueryable,System.String,System.Object[])
-AsEnumerable()
-Count(System.Linq.IQueryable)
-Count(System.Linq.IQueryable,System.String,System.Object[])
-Distinct(System.Linq.IQueryable)
-First(System.Linq.IQueryable)
-First(System.Linq.IQueryable,System.String,System.Object[])
-FirstOrDefault(System.Linq.IQueryable)
-FirstOrDefault(System.Linq.IQueryable,System.String,System.Object[])
-GroupBy(System.Linq.IQueryable,System.String,System.String,System.Object[])
-GroupBy(System.Linq.IQueryable,System.String,System.String)
-GroupBy(System.Linq.IQueryable,System.String,System.Object[])
-GroupByMany(System.Collections.Generic.IEnumerable`1<TElement>,System.String[])
-GroupByMany(System.Collections.Generic.IEnumerable`1<TElement>,System.Func`2<TElement,System.Object>[])
-GroupByManyInternal(System.Collections.Generic.IEnumerable`1<TElement>,System.Func`2<TElement,System.Object>[],System.Int32)
-Join(System.Linq.IQueryable,System.Collections.IEnumerable,System.String,System.String,System.String,System.Object[])
-Join(System.Linq.IQueryable`1<TElement>,System.Collections.Generic.IEnumerable`1<TElement>,System.String,System.String,System.String,System.Object[])
-Last(System.Linq.IQueryable)
-LastOrDefault(System.Linq.IQueryable)
-OrderBy(System.Linq.IQueryable`1<TSource>,System.String,System.Object[])
-OrderBy(System.Linq.IQueryable,System.String,System.Object[])
-Page(System.Linq.IQueryable,System.Int32,System.Int32)
-Page(System.Linq.IQueryable`1<TSource>,System.Int32,System.Int32)
-PageResult(System.Linq.IQueryable,System.Int32,System.Int32)
-PageResult(System.Linq.IQueryable`1<TSource>,System.Int32,System.Int32)
-Reverse(System.Linq.IQueryable)
-Select(System.Linq.IQueryable,System.String,System.Object[])
-Select(System.Linq.IQueryable,System.String,System.Object[])
-Select(System.Linq.IQueryable,System.Type,System.String,System.Object[])
-SelectMany(System.Linq.IQueryable,System.String,System.Object[])
-SelectMany(System.Linq.IQueryable,System.Type,System.String,System.Object[])
-SelectManyInternal(System.Linq.IQueryable,System.Type,System.String,System.Object[])
-SelectMany(System.Linq.IQueryable,System.String,System.Object[])
-SelectMany(System.Linq.IQueryable,System.String,System.String,System.Object[],System.Object[])
-SelectMany(System.Linq.IQueryable,System.String,System.String,System.String,System.String,System.Object[],System.Object[])
-Single(System.Linq.IQueryable)
-SingleOrDefault(System.Linq.IQueryable)
-Skip(System.Linq.IQueryable,System.Int32)
-SkipWhile(System.Linq.IQueryable,System.String,System.Object[])
-Sum(System.Linq.IQueryable)
-Take(System.Linq.IQueryable,System.Int32)
-TakeWhile(System.Linq.IQueryable,System.String,System.Object[])
-ThenBy(System.Linq.IOrderedQueryable`1<TSource>,System.String,System.Object[])
-ThenBy(System.Linq.IOrderedQueryable,System.String,System.Object[])
-Where(System.Linq.IQueryable`1<TSource>,System.String,System.Object[])
-Where(System.Linq.IQueryable,System.String,System.Object[])
-CreateQuery(System.Reflection.MethodInfo,System.Linq.IQueryable)
-CreateQuery(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
-CreateQuery(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression)
-Execute(System.Reflection.MethodInfo,System.Linq.IQueryable)
-Execute(System.Reflection.MethodInfo,System.Linq.IQueryable)
-Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
-Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression)
-Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
-Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression)
-GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)
-GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)
+.cctor()
+OptimizeExpression(System.Linq.Expressions.Expression)
+Aggregate(System.Linq.IQueryable,System.String,System.String)
+Any(System.Linq.IQueryable)
+Any(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Any(System.Linq.IQueryable,System.String,System.Object[])
+Any(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+AsEnumerable()
+Count(System.Linq.IQueryable)
+Count(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Count(System.Linq.IQueryable,System.String,System.Object[])
+Count(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+DefaultIfEmpty(System.Linq.IQueryable)
+DefaultIfEmpty(System.Linq.IQueryable,System.Object)
+Distinct(System.Linq.IQueryable)
+First(System.Linq.IQueryable)
+First(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+First(System.Linq.IQueryable,System.String,System.Object[])
+First(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+FirstOrDefault(System.Linq.IQueryable)
+FirstOrDefault(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+FirstOrDefault(System.Linq.IQueryable,System.String,System.Object[])
+FirstOrDefault(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+GroupBy(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.String,System.Object[])
+GroupBy(System.Linq.IQueryable,System.String,System.String,System.Object[])
+GroupBy(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.String)
+GroupBy(System.Linq.IQueryable,System.String,System.String)
+GroupBy(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+GroupBy(System.Linq.IQueryable,System.String,System.Object[])
+GroupByMany(System.Collections.Generic.IEnumerable`1<TElement>,System.Linq.Dynamic.Core.ParsingConfig,System.String[])
+GroupByMany(System.Collections.Generic.IEnumerable`1<TElement>,System.String[])
+GroupByMany(System.Collections.Generic.IEnumerable`1<TElement>,System.Func`2<TElement,System.Object>[])
+GroupByManyInternal(System.Collections.Generic.IEnumerable`1<TElement>,System.Func`2<TElement,System.Object>[],System.Int32)
+GroupJoin(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.Collections.IEnumerable,System.String,System.String,System.String,System.Object[])
+GroupJoin(System.Linq.IQueryable,System.Collections.IEnumerable,System.String,System.String,System.String,System.Object[])
+Join(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.Collections.IEnumerable,System.String,System.String,System.String,System.Object[])
+Join(System.Linq.IQueryable,System.Collections.IEnumerable,System.String,System.String,System.String,System.Object[])
+Join(System.Linq.IQueryable`1<TElement>,System.Linq.Dynamic.Core.ParsingConfig,System.Collections.Generic.IEnumerable`1<TElement>,System.String,System.String,System.String,System.Object[])
+Join(System.Linq.IQueryable`1<TElement>,System.Collections.Generic.IEnumerable`1<TElement>,System.String,System.String,System.String,System.Object[])
+Last(System.Linq.IQueryable)
+Last(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Last(System.Linq.IQueryable,System.String,System.Object[])
+Last(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+LastOrDefault(System.Linq.IQueryable)
+LastOrDefault(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+LastOrDefault(System.Linq.IQueryable,System.String,System.Object[])
+LastOrDefault(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+OrderBy(System.Linq.IQueryable`1<TSource>,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+OrderBy(System.Linq.IQueryable`1<TSource>,System.String,System.Object[])
+OrderBy(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+OrderBy(System.Linq.IQueryable,System.String,System.Object[])
+Page(System.Linq.IQueryable,System.Int32,System.Int32)
+Page(System.Linq.IQueryable`1<TSource>,System.Int32,System.Int32)
+PageResult(System.Linq.IQueryable,System.Int32,System.Int32)
+PageResult(System.Linq.IQueryable`1<TSource>,System.Int32,System.Int32)
+Reverse(System.Linq.IQueryable)
+Select(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Select(System.Linq.IQueryable,System.String,System.Object[])
+Select(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Select(System.Linq.IQueryable,System.String,System.Object[])
+Select(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.Type,System.String,System.Object[])
+Select(System.Linq.IQueryable,System.Type,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.Type,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.Type,System.String,System.Object[])
+SelectManyInternal(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.Type,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.String,System.Object[])
+SelectMany(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.String,System.Object[],System.Object[])
+SelectMany(System.Linq.IQueryable,System.String,System.String,System.Object[],System.Object[])
+SelectMany(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.String,System.String,System.String,System.Object[],System.Object[])
+SelectMany(System.Linq.IQueryable,System.String,System.String,System.String,System.String,System.Object[],System.Object[])
+Single(System.Linq.IQueryable)
+Single(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Single(System.Linq.IQueryable,System.String,System.Object[])
+Single(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+SingleOrDefault(System.Linq.IQueryable)
+SingleOrDefault(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+SingleOrDefault(System.Linq.IQueryable,System.String,System.Object[])
+SingleOrDefault(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+Skip(System.Linq.IQueryable,System.Int32)
+SkipWhile(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+SkipWhile(System.Linq.IQueryable,System.String,System.Object[])
+Sum(System.Linq.IQueryable)
+Take(System.Linq.IQueryable,System.Int32)
+TakeWhile(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+TakeWhile(System.Linq.IQueryable,System.String,System.Object[])
+ThenBy(System.Linq.IOrderedQueryable`1<TSource>,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+ThenBy(System.Linq.IOrderedQueryable`1<TSource>,System.String,System.Object[])
+ThenBy(System.Linq.IOrderedQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+ThenBy(System.Linq.IOrderedQueryable,System.String,System.Object[])
+Where(System.Linq.IQueryable`1<TSource>,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Where(System.Linq.IQueryable`1<TSource>,System.String,System.Object[])
+Where(System.Linq.IQueryable,System.Linq.Dynamic.Core.ParsingConfig,System.String,System.Object[])
+Where(System.Linq.IQueryable,System.String,System.Object[])
+Where(System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+CheckOuterAndInnerTypes(System.Boolean,System.Type,System.Type,System.String,System.String,System.Linq.Expressions.LambdaExpression&,System.Linq.Expressions.LambdaExpression&,System.Object[])
+CreateQuery(System.Reflection.MethodInfo,System.Linq.IQueryable)
+CreateQuery(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+CreateQuery(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression)
+Execute(System.Reflection.MethodInfo,System.Linq.IQueryable)
+Execute(System.Reflection.MethodInfo,System.Linq.IQueryable)
+Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression)
+Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.LambdaExpression)
+Execute(System.Reflection.MethodInfo,System.Linq.IQueryable,System.Linq.Expressions.Expression)
+GetMethod(System.String,System.Int32,System.Func`2<System.Reflection.MethodInfo,System.Boolean>)

diff --git a/report/System.Linq.Dynamic.Core_ExpressionHelper.htm b/report/System.Linq.Dynamic.Core_ExpressionHelper.htm new file mode 100644 index 00000000..34c88029 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_ExpressionHelper.htm @@ -0,0 +1,274 @@ + + + + + +System.Linq.Dynamic.Core.Parser.ExpressionHelper - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.ExpressionHelper
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionHelper.cs
Covered lines:120
Uncovered lines:5
Coverable lines:125
Total lines:199
Line coverage:96%
Branch coverage:70.4%
+

Metrics

+ + + + + + + + + + + + + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
ConvertNumericTypeToBiggestCommonTypeForBinaryOperator(...)44419430410071.11
GenerateAdd(...)10100100
GenerateStringConcat(...)10100100
GenerateSubtract(...)10100100
GenerateEqual(...)10100100
GenerateNotEqual(...)10100100
GenerateGreaterThan(...)81610077.78
GenerateGreaterThanEqual(...)81610077.78
GenerateLessThan(...)81610077.78
GenerateLessThanEqual(...)81610077.78
OptimizeForEqualityIfPossible(...)7167555.56
OptimizeStringForEqualityIfPossible(...)5477.7880
GetStaticMethod(...)10100100
GenerateStaticMethodCall(...)10100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionHelper.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Globalization;
 2using System.Linq.Expressions;
 3using System.Reflection;
 4
 5namespace System.Linq.Dynamic.Core.Parser
 6{
 7    internal static class ExpressionHelper
 8    {
 9        public static void ConvertNumericTypeToBiggestCommonTypeForBinaryOperator(ref Expression left, ref Expression ri
 3710        {
 3711             if (left.Type == right.Type)
 912            {
 913                return;
 14            }
 15
 2816             if (left.Type == typeof(UInt64) || right.Type == typeof(UInt64))
 417            {
 418                 right = right.Type != typeof(UInt64) ? Expression.Convert(right, typeof(UInt64)) : right;
 419                 left = left.Type != typeof(UInt64) ? Expression.Convert(left, typeof(UInt64)) : left;
 420            }
 2421             else if (left.Type == typeof(Int64) || right.Type == typeof(Int64))
 422            {
 423                 right = right.Type != typeof(Int64) ? Expression.Convert(right, typeof(Int64)) : right;
 424                 left = left.Type != typeof(Int64) ? Expression.Convert(left, typeof(Int64)) : left;
 425            }
 2026             else if (left.Type == typeof(UInt32) || right.Type == typeof(UInt32))
 427            {
 428                 right = right.Type != typeof(UInt32) ? Expression.Convert(right, typeof(UInt32)) : right;
 429                 left = left.Type != typeof(UInt32) ? Expression.Convert(left, typeof(UInt32)) : left;
 430            }
 1631             else if (left.Type == typeof(Int32) || right.Type == typeof(Int32))
 1032            {
 1033                 right = right.Type != typeof(Int32) ? Expression.Convert(right, typeof(Int32)) : right;
 1034                 left = left.Type != typeof(Int32) ? Expression.Convert(left, typeof(Int32)) : left;
 1035            }
 636             else if (left.Type == typeof(UInt16) || right.Type == typeof(UInt16))
 237            {
 238                 right = right.Type != typeof(UInt16) ? Expression.Convert(right, typeof(UInt16)) : right;
 239                 left = left.Type != typeof(UInt16) ? Expression.Convert(left, typeof(UInt16)) : left;
 240            }
 441             else if (left.Type == typeof(Int16) || right.Type == typeof(Int16))
 242            {
 243                 right = right.Type != typeof(Int16) ? Expression.Convert(right, typeof(Int16)) : right;
 244                 left = left.Type != typeof(Int16) ? Expression.Convert(left, typeof(Int16)) : left;
 245            }
 246             else if (left.Type == typeof(Byte) || right.Type == typeof(Byte))
 247            {
 248                 right = right.Type != typeof(Byte) ? Expression.Convert(right, typeof(Byte)) : right;
 249                 left = left.Type != typeof(Byte) ? Expression.Convert(left, typeof(Byte)) : left;
 250            }
 3751        }
 52
 53        public static Expression GenerateAdd(Expression left, Expression right)
 1454        {
 1455            return Expression.Add(left, right);
 1456        }
 57
 58        public static Expression GenerateStringConcat(Expression left, Expression right)
 1459        {
 1460            return GenerateStaticMethodCall("Concat", left, right);
 1461        }
 62
 63        public static Expression GenerateSubtract(Expression left, Expression right)
 164        {
 165            return Expression.Subtract(left, right);
 166        }
 67
 68        public static Expression GenerateEqual(Expression left, Expression right)
 20169        {
 20170            OptimizeForEqualityIfPossible(ref left, ref right);
 20171            return Expression.Equal(left, right);
 20172        }
 73
 74        public static Expression GenerateNotEqual(Expression left, Expression right)
 775        {
 776            OptimizeForEqualityIfPossible(ref left, ref right);
 777            return Expression.NotEqual(left, right);
 778        }
 79
 80        public static Expression GenerateGreaterThan(Expression left, Expression right)
 4281        {
 4282             if (left.Type == typeof(string))
 183            {
 184                return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
 85            }
 86
 4187             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 288            {
 289                 var leftPart = left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetUnderlyingType(left.Typ
 290                 var rightPart = right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right
 291                return Expression.GreaterThan(leftPart, rightPart);
 92            }
 93
 3994            return Expression.GreaterThan(left, right);
 4295        }
 96
 97        public static Expression GenerateGreaterThanEqual(Expression left, Expression right)
 398        {
 399             if (left.Type == typeof(string))
 1100            {
 1101                return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Consta
 102            }
 103
 2104             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 1105            {
 1106                 return Expression.GreaterThanOrEqual(left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetU
 1107                    right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right.Type)) : ri
 108            }
 109
 1110            return Expression.GreaterThanOrEqual(left, right);
 3111        }
 112
 113        public static Expression GenerateLessThan(Expression left, Expression right)
 8114        {
 8115             if (left.Type == typeof(string))
 1116            {
 1117                return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
 118            }
 119
 7120             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 4121            {
 4122                 return Expression.LessThan(left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetUnderlyingT
 4123                    right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right.Type)) : ri
 124            }
 125
 3126            return Expression.LessThan(left, right);
 8127        }
 128
 129        public static Expression GenerateLessThanEqual(Expression left, Expression right)
 4130        {
 4131             if (left.Type == typeof(string))
 1132            {
 1133                return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(
 134            }
 135
 3136             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 1137            {
 1138                 return Expression.LessThanOrEqual(left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetUnde
 1139                    right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right.Type)) : ri
 140            }
 141
 2142            return Expression.LessThanOrEqual(left, right);
 4143        }
 144
 145        public static void OptimizeForEqualityIfPossible(ref Expression left, ref Expression right)
 208146        {
 147            // The goal here is to provide the way to convert some types from the string form in a way that is compatibl
 148            //
 149            // The Expression.Call(typeof(Guid).GetMethod("Parse"), right); does the job only for Linq to Object but Lin
 150            //
 208151            Type leftType = left.Type;
 208152            Type rightType = right.Type;
 153
 208154             if (rightType == typeof(string) && right.NodeType == ExpressionType.Constant)
 26155            {
 26156                 right = OptimizeStringForEqualityIfPossible((string)((ConstantExpression)right).Value, leftType) ?? righ
 26157            }
 158
 208159             if (leftType == typeof(string) && left.NodeType == ExpressionType.Constant)
 0160            {
 0161                 left = OptimizeStringForEqualityIfPossible((string)((ConstantExpression)left).Value, rightType) ?? left;
 0162            }
 208163        }
 164
 165        public static Expression OptimizeStringForEqualityIfPossible(string text, Type type)
 28166        {
 28167             if (type == typeof(DateTime) && DateTime.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.None, o
 0168            {
 0169                return Expression.Constant(dateTime, typeof(DateTime));
 170            }
 171#if !NET35
 28172             if (type == typeof(Guid) && Guid.TryParse(text, out Guid guid))
 1173            {
 1174                return Expression.Constant(guid, typeof(Guid));
 175            }
 176#else
 177            try
 178            {
 179                return Expression.Constant(new Guid(text));
 180            }
 181            catch
 182            {
 183                // Doing it in old fashion way when no TryParse interface was provided by .NET
 184            }
 185#endif
 27186            return null;
 28187        }
 188
 189        static MethodInfo GetStaticMethod(string methodName, Expression left, Expression right)
 18190        {
 18191            return left.Type.GetMethod(methodName, new[] { left.Type, right.Type });
 18192        }
 193
 194        static Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right)
 18195        {
 18196            return Expression.Call(null, GetStaticMethod(methodName, left, right), new[] { left, right });
 18197        }
 198    }
 199}
+
+
+ +
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_ExpressionParser.htm b/report/System.Linq.Dynamic.Core_ExpressionParser.htm index ef55f029..88bdac55 100644 --- a/report/System.Linq.Dynamic.Core_ExpressionParser.htm +++ b/report/System.Linq.Dynamic.Core_ExpressionParser.htm @@ -3,7 +3,7 @@ -System.Linq.Dynamic.Core.ExpressionParser - Coverage Report +System.Linq.Dynamic.Core.Parser.ExpressionParser - Coverage Report

Summary

@@ -13,2900 +13,1980 @@

Summary

-Class:System.Linq.Dynamic.Core.ExpressionParser +Class:System.Linq.Dynamic.Core.Parser.ExpressionParser Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ExpressionParser.cs -Covered lines:1323 -Uncovered lines:187 -Coverable lines:1510 -Total lines:2670 -Line coverage:87.6% -Branch coverage:75.3% +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs +Covered lines:996 +Uncovered lines:194 +Coverable lines:1190 +Total lines:1824 +Line coverage:83.6% +Branch coverage:75.4%

Metrics

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.cctor()10100100
UpdatePredefinedTypes(...)2200
.ctor(...)4810085.71
ProcessParameters(...)6810085.71
ProcessValues(...)44100100
AddSymbol(...)228066.67
Parse(...)34100100
ParseOrdering(...)1264100100
ParseConditionalOperator()22100100
ParseNullCoalescingOperator()22100100
ParseLambdaOperator()5438.4640
ParseIsNull()22100100
ParseOrOperator()32100100
ParseAndOperator()32100100
ParseIn()15204888.4678.26
ParseLogicalAndOrOperator()96472.4161.54
ParseComparisonOperator()4422937690.6779.07
ParseEnumToConstantExpression(...)10100100
ParseConstantExpressionToEnum(...)2275100
ParseShiftOperator()5810085.71
ParseAdditive()71686.9666.67
ParseMultiplicative()103277.7836.36
ParseUnary()9852.1757.14
ParsePrimary()34100100
ParsePrimaryStart()7988.8960
ParseStringLiteral()3461.5440
ParseIntegerLiteral()32419430488.0682.22
ParseRealLiteral()10100100
TryParseAsFloat(...)44100100
TryParseAsDouble(...)5891.6785.71
CreateLiteral(...)10100100
ParseParenExpression()10100100
ParseIdentifier()193276893.3390.32
ParseIt()2283.3366.67
ParseParent()2283.3366.67
ParseRoot()2283.3366.67
ParseIif()2287.566.67
GenerateConditional(...)1651258.3342.11
ParseNew()20409696.5592
CreateArrayInitializerExpression(...)51610077.78
CreateNewExpression(...)61694.1288.89
ParseLambdaInvocation(...)2200
ParseTypeAccess(...)13102490.3271.43
GenerateConversion(...)2140964444
ParseMemberAccess(...)18409688.8980
FindGenericType(...)81610088.89
FindType(...)1412873.6866.67
ParseAggregate(...)126497.7892.31
ParseArgumentList()22100100
ParseArguments()22100100
ParseElementAccess(...)73257.1436.36
IsPredefinedType(...)4485.7180
IsNullableType(...)20100100
ToNullableType(...)348060
GetNonNullableType(...)32100100
GetTypeName(...)2285.7166.67
TryGetMemberName(...)4461.5460
IsNumericType(...)10100100
IsSignedIntegralType(...)10100100
IsUnsignedIntegralType(...)10100100
GetNumericTypeKind(...)141683.3377.78
IsEnumType(...)10100100
CheckAndPromoteOperand(...)2200
CheckAndPromoteOperands(...)22100100
IncompatibleOperandsError(...)10100100
FindPropertyOrField(...)7493.3380
FindMethod(...)52100100
FindIndexer(...)6477.7860
SelfAndBaseTypes(...)22100100
AddInterface(...)32100100
FindBestMethod(...)58100100
IsApplicable(...)51694.7488.89
PromoteExpression(...)191638495.3593.10
ParseNumber(...)23419430471.1971.11
ParseEnum(...)2266.6766.67
IsCompatibleWith(...)71167772169593.88
IsBetterThan(...)51693.7577.78
CompareConversions(...)1251294.7489.47
GenerateEqual(...)10100100
GenerateNotEqual(...)10100100
GenerateGreaterThan(...)81610077.78
GenerateGreaterThanEqual(...)81610077.78
GenerateLessThan(...)81610077.78
GenerateLessThanEqual(...)81610077.78
GenerateAdd(...)3266.6766.67
GenerateSubtract(...)1000
GenerateStringConcat(...)10100100
GetStaticMethod(...)10100100
GenerateStaticMethodCall(...)10100100
OptimizeForEqualityIfPossible(...)7167555.56
OptimizeStringForEqualityIfPossible(...)5471.4360
TokenIdentifierIs(...)20100100
GetIdentifier()3285.7166.67
ParseError(...)10100100
ParseError(...)10100100
CreateKeywords()94100100
ResetDynamicLinqTypes()10100100
SelfAndBaseClasses()42100100
.ctor(...)4810085.71
ProcessParameters(...)6410080
ProcessValues(...)44100100
AddSymbol(...)22100100
Parse(...)3485.7180
ParseOrdering(...)1264100100
ParseConditionalOperator()22100100
ParseNullCoalescingOperator()22100100
ParseLambdaOperator()5438.4640
ParseIsNull()22100100
ParseOrOperator()32100100
ParseAndOperator()32100100
ParseIn()12102484.9180.95
ParseLogicalAndOrOperator()1725692.3188.24
ParseComparisonOperator()5873400328677.36
HasImplicitConversion(...)10100100
ParseEnumToConstantExpression(...)10100100
ParseConstantExpressionToEnum(...)2270100
ParseShiftOperator()5810085.71
ParseAdditive()71610088.89
ParseMultiplicative()103210072.73
ParseUnary()9852.1757.14
ParsePrimary()48100100
ParsePrimaryStart()7910080
ParseStringLiteral()3457.1440
ParseIntegerLiteral()34838860886.1182.98
ParseRealLiteral()10100100
TryParseAsFloat(...)44100100
TryParseAsDecimal(...)44100100
TryParseAsDouble(...)5891.6785.71
ParseParenExpression()10100100
ParseIdentifier()193276891.6790.32
ParseIt()2271.4366.67
ParseParent()2271.4366.67
ParseRoot()2271.4366.67
ParseIif()2277.7866.67
GenerateConditional(...)1651253.8542.11
ParseNew()231638491.8989.66
CreateArrayInitializerExpression(...)51610077.78
CreateNewExpression(...)1325670.3782.35
ParseLambdaInvocation(...)2200
ParseTypeAccess(...)13102487.8871.43
GenerateConversion(...)21409641.9444
ParseMemberAccess(...)201638481.8279.31
FindType(...)1412861.5466.67
ParseAggregate(...)1451296.9294.74
ParseArgumentList()22100100
ParseArguments()22100100
ParseElementAccess(...)7325036.36
ToNullableType(...)3471.4360
TryGetMemberName(...)4461.5460
CheckAndPromoteOperand(...)2200
CheckAndPromoteOperands(...)22100100
IncompatibleOperandError(...)1000
IncompatibleOperandsError(...)10100100
FindPropertyOrField(...)7488.2480
TokenIdentifierIs(...)20100100
GetIdentifier()3266.6766.67
ParseError(...)32100100
ParseError(...)10100100
.cctor()10100100

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ExpressionParser.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + +
#LineLine coverage
 1using System.Collections.Generic;
 2using System.ComponentModel;
 3using System.Linq.Expressions;
 4using System.Reflection;
 5using System.Collections;
 6using System.Globalization;
 7using System.Linq.Dynamic.Core.Exceptions;
 8using System.Linq.Dynamic.Core.Tokenizer;
 9
 10namespace System.Linq.Dynamic.Core
 11{
 12    internal class ExpressionParser
 13    {
 14        interface ILogicalSignatures
 15        {
 16            void F(bool x, bool y);
 17            void F(bool? x, bool? y);
 18        }
 19
 20        interface IShiftSignatures
 21        {
 22            void F(int x, int y);
 23            void F(uint x, int y);
 24            void F(long x, int y);
 25            void F(ulong x, int y);
 26            void F(int? x, int y);
 27            void F(uint? x, int y);
 28            void F(long? x, int y);
 29            void F(ulong? x, int y);
 30            void F(int x, int? y);
 31            void F(uint x, int? y);
 32            void F(long x, int? y);
 33            void F(ulong x, int? y);
 34            void F(int? x, int? y);
 35            void F(uint? x, int? y);
 36            void F(long? x, int? y);
 37            void F(ulong? x, int? y);
 38        }
 39
 40        interface IArithmeticSignatures
 41        {
 42            void F(int x, int y);
 43            void F(uint x, uint y);
 44            void F(long x, long y);
 45            void F(ulong x, ulong y);
 46            void F(float x, float y);
 47            void F(double x, double y);
 48            void F(decimal x, decimal y);
 49            void F(int? x, int? y);
 50            void F(uint? x, uint? y);
 51            void F(long? x, long? y);
 52            void F(ulong? x, ulong? y);
 53            void F(float? x, float? y);
 54            void F(double? x, double? y);
 55            void F(decimal? x, decimal? y);
 56        }
 1using JetBrains.Annotations;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.ComponentModel;
 5using System.Globalization;
 6using System.Linq.Dynamic.Core.Exceptions;
 7using System.Linq.Dynamic.Core.Parser.SupportedMethods;
 8using System.Linq.Dynamic.Core.Parser.SupportedOperands;
 9using System.Linq.Dynamic.Core.Tokenizer;
 10using System.Linq.Dynamic.Core.Validation;
 11using System.Linq.Expressions;
 12using System.Reflection;
 13
 14namespace System.Linq.Dynamic.Core.Parser
 15{
 16    /// <summary>
 17    /// ExpressionParser
 18    /// </summary>
 19    public class ExpressionParser
 20    {
 121        static readonly string methodOrderBy = nameof(Queryable.OrderBy);
 122        static readonly string methodOrderByDescending = nameof(Queryable.OrderByDescending);
 123        static readonly string methodThenBy = nameof(Queryable.ThenBy);
 124        static readonly string methodThenByDescending = nameof(Queryable.ThenByDescending);
 25
 26        private readonly ParsingConfig _parsingConfig;
 27        private readonly KeywordsHelper _keywordsHelper;
 28        private readonly TextParser _textParser;
 29        private readonly Dictionary<string, object> _internals;
 30        private readonly Dictionary<string, object> _symbols;
 31
 32        private IDictionary<string, object> _externals;
 33        private ParameterExpression _it;
 34        private ParameterExpression _parent;
 35        private ParameterExpression _root;
 36        private Type _resultType;
 37        private bool _createParameterCtor;
 38
 39        /// <summary>
 40        /// Initializes a new instance of the <see cref="ExpressionParser"/> class.
 41        /// </summary>
 42        /// <param name="parameters">The parameters.</param>
 43        /// <param name="expression">The expression.</param>
 44        /// <param name="values">The values.</param>
 45        /// <param name="parsingConfig">The parsing configuration.</param>
 49346        public ExpressionParser([CanBeNull] ParameterExpression[] parameters, [NotNull] string expression, [CanBeNull] o
 49347        {
 49348            Check.NotEmpty(expression, nameof(expression));
 49
 49350            _symbols = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
 49351            _internals = new Dictionary<string, object>();
 52
 49353             if (parameters != null)
 49354            {
 49355                ProcessParameters(parameters);
 49256            }
 57
 58        interface IRelationalSignatures : IArithmeticSignatures
 59        {
 60            void F(string x, string y);
 61            void F(char x, char y);
 62            void F(DateTime x, DateTime y);
 63            void F(DateTimeOffset x, DateTimeOffset y);
 64            void F(TimeSpan x, TimeSpan y);
 65            void F(char? x, char? y);
 66            void F(DateTime? x, DateTime? y);
 67            void F(DateTimeOffset? x, DateTimeOffset? y);
 68            void F(TimeSpan? x, TimeSpan? y);
 69        }
 70
 71        interface IEqualitySignatures : IRelationalSignatures
 72        {
 73            void F(bool x, bool y);
 74            void F(bool? x, bool? y);
 49258             if (values != null)
 48259            {
 48260                ProcessValues(values);
 48261            }
 62
 49263             _parsingConfig = parsingConfig ?? ParsingConfig.Default;
 64
 49265            _keywordsHelper = new KeywordsHelper(_parsingConfig);
 49266            _textParser = new TextParser(expression);
 49267        }
 68
 69        void ProcessParameters(ParameterExpression[] parameters)
 49370        {
 203971            foreach (ParameterExpression pe in parameters.Where(p => !string.IsNullOrEmpty(p.Name)))
 3372            {
 3373                AddSymbol(pe.Name, pe);
 3274            }
 75
 76            // Disabled 4 lines below because of : https://github.com/StefH/System.Linq.Dynamic.Core/issues/19
 77            //void F(DateTime x, string y);
 78            //void F(DateTime? x, string y);
 79            //void F(string x, DateTime y);
 80            //void F(string x, DateTime? y);
 76            // If there is only 1 ParameterExpression, do also allow access using 'it'
 49277             if (parameters.Length == 1)
 47378            {
 47379                _parent = _it;
 47380                _it = parameters[0];
 81
 82            void F(Guid x, Guid y);
 83            void F(Guid? x, Guid? y);
 84            void F(Guid x, string y);
 85            void F(Guid? x, string y);
 86            void F(string x, Guid y);
 87            void F(string x, Guid? y);
 88        }
 89
 90        interface IAddSignatures : IArithmeticSignatures
 91        {
 92            void F(DateTime x, TimeSpan y);
 93            void F(TimeSpan x, TimeSpan y);
 94            void F(DateTime? x, TimeSpan? y);
 95            void F(TimeSpan? x, TimeSpan? y);
 96        }
 97
 98        interface ISubtractSignatures : IAddSignatures
 99        {
 100            void F(DateTime x, DateTime y);
 101            void F(DateTime? x, DateTime? y);
 102        }
 103
 104        interface INegationSignatures
 105        {
 106            void F(int x);
 107            void F(long x);
 108            void F(float x);
 109            void F(double x);
 110            void F(decimal x);
 111            void F(int? x);
 112            void F(long? x);
 113            void F(float? x);
 114            void F(double? x);
 115            void F(decimal? x);
 116        }
 117
 118        interface INotSignatures
 119        {
 120            void F(bool x);
 121            void F(bool? x);
 122        }
 123
 124        interface IEnumerableSignatures
 125        {
 126            void Where(bool predicate);
 127            void Any();
 128            void Any(bool predicate);
 129            void First(bool predicate);
 130            void FirstOrDefault(bool predicate);
 131            void Single(bool predicate);
 132            void SingleOrDefault(bool predicate);
 133            void Last(bool predicate);
 134            void LastOrDefault(bool predicate);
 135            void All(bool predicate);
 136            void Count();
 137            void Count(bool predicate);
 138            void Min(object selector);
 139            void Max(object selector);
 140            void Sum(int selector);
 141            void Sum(int? selector);
 142            void Sum(long selector);
 143            void Sum(long? selector);
 144            void Sum(float selector);
 145            void Sum(float? selector);
 146            void Sum(double selector);
 147            void Sum(double? selector);
 148            void Sum(decimal selector);
 149            void Sum(decimal? selector);
 150            void Average(int selector);
 151            void Average(int? selector);
 152            void Average(long selector);
 153            void Average(long? selector);
 154            void Average(float selector);
 155            void Average(float? selector);
 156            void Average(double selector);
 157            void Average(double? selector);
 158            void Average(decimal selector);
 159            void Average(decimal? selector);
 160            void Select(object selector);
 161            void SelectMany(object selector);
 162            void OrderBy(object selector);
 163            void OrderByDescending(object selector);
 164            void ThenBy(object selector);
 165            void ThenByDescending(object selector);
 166            void Contains(object selector);
 167            void Skip(int count);
 168            void SkipWhile(bool predicate);
 169            void Take(int count);
 170            void TakeWhile(bool predicate);
 171            void Distinct();
 172            void GroupBy(object selector);
 47382                 if (_root == null)
 47383                {
 47384                    _root = _it;
 47385                }
 47386            }
 49287        }
 88
 89        void ProcessValues(object[] values)
 48290        {
 124891             for (int i = 0; i < values.Length; i++)
 14292            {
 14293                object value = values[i];
 94                IDictionary<string, object> externals;
 95
 14296                 if (i == values.Length - 1 && (externals = value as IDictionary<string, object>) != null)
 497                {
 498                    _externals = externals;
 499                }
 100                else
 138101                {
 138102                    AddSymbol("@" + i.ToString(CultureInfo.InvariantCulture), value);
 138103                }
 142104            }
 482105        }
 106
 107        private void AddSymbol(string name, object value)
 171108        {
 171109             if (_symbols.ContainsKey(name))
 1110            {
 1111                throw ParseError(Res.DuplicateIdentifier, name);
 112            }
 113
 170114            _symbols.Add(name, value);
 170115        }
 116
 117        /// <summary>
 118        /// Uses the TextParser to parse the string into the specified result type.
 119        /// </summary>
 120        /// <param name="resultType">Type of the result.</param>
 121        /// <param name="createParameterCtor">if set to <c>true</c> [create parameter ctor].</param>
 122        /// <returns>Expression</returns>
 123        public Expression Parse([CanBeNull] Type resultType, bool createParameterCtor = true)
 467124        {
 467125            _resultType = resultType;
 467126            _createParameterCtor = createParameterCtor;
 127
 467128            int exprPos = _textParser.CurrentToken.Pos;
 467129            Expression expr = ParseConditionalOperator();
 130
 438131             if (resultType != null)
 53132            {
 53133                 if ((expr = ExpressionPromoter.Promote(expr, resultType, true, false)) == null)
 0134                {
 0135                    throw ParseError(exprPos, Res.ExpressionTypeMismatch, TypeHelper.GetTypeName(resultType));
 136                }
 53137            }
 138
 438139            _textParser.ValidateToken(TokenId.End, Res.SyntaxError);
 140
 434141            return expr;
 434142        }
 143
 144#pragma warning disable 0219
 145        internal IList<DynamicOrdering> ParseOrdering(bool forceThenBy = false)
 25146        {
 25147            var orderings = new List<DynamicOrdering>();
 29148            while (true)
 29149            {
 29150                Expression expr = ParseConditionalOperator();
 27151                bool ascending = true;
 27152                 if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending"))
 1153                {
 1154                    _textParser.NextToken();
 1155                }
 26156                 else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending"))
 4157                {
 4158                    _textParser.NextToken();
 4159                    ascending = false;
 4160                }
 161
 162                string methodName;
 27163                 if (forceThenBy || orderings.Count > 0)
 6164                {
 6165                     methodName = ascending ? methodThenBy : methodThenByDescending;
 6166                }
 167                else
 21168                {
 21169                     methodName = ascending ? methodOrderBy : methodOrderByDescending;
 21170                }
 171
 27172                orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending, MethodName = methodName });
 173
 174            //Executors
 175            void Single();
 176            void SingleOrDefault();
 177            void First();
 178            void FirstOrDefault();
 179            void Last();
 180            void LastOrDefault();
 181        }
 182
 183        // These shorthands have different name than actual type and therefore not recognized by default from the _prede
 184        //
 1185        static readonly Dictionary<string, Type> _predefinedTypesShorthands = new Dictionary<string, Type>
 1186        {
 1187            { "int", typeof(int) },
 1188            { "uint", typeof(uint) },
 1189            { "short", typeof(short) },
 1190            { "ushort", typeof(ushort) },
 1191            { "long", typeof(long) },
 1192            { "ulong", typeof(ulong) },
 1193            { "bool", typeof(bool) },
 1194            { "float", typeof(float) },
 1195        };
 196
 1197        static readonly Dictionary<Type, int> _predefinedTypes = new Dictionary<Type, int> {
 1198            { typeof(object), 0 },
 1199            { typeof(bool), 0 },
 1200            { typeof(char), 0 },
 1201            { typeof(string), 0 },
 1202            { typeof(sbyte), 0 },
 1203            { typeof(byte), 0 },
 1204            { typeof(short), 0 },
 1205            { typeof(ushort), 0 },
 1206            { typeof(int), 0 },
 1207            { typeof(uint), 0 },
 1208            { typeof(long), 0 },
 1209            { typeof(ulong), 0 },
 1210            { typeof(float), 0 },
 1211            { typeof(double), 0 },
 1212            { typeof(decimal), 0 },
 1213            { typeof(DateTime), 0 },
 1214            { typeof(DateTimeOffset), 0 },
 1215            { typeof(TimeSpan), 0 },
 1216            { typeof(Guid), 0 },
 1217            { typeof(Math), 0 },
 1218            { typeof(Convert), 0 },
 1219            { typeof(Uri), 0 }
 1220        };
 221
 1222        static readonly Expression TrueLiteral = Expression.Constant(true);
 1223        static readonly Expression FalseLiteral = Expression.Constant(false);
 1224        static readonly Expression NullLiteral = Expression.Constant(null);
 225
 226        const string SYMBOL_IT = "$";
 227        const string SYMBOL_PARENT = "^";
 228        const string SYMBOL_ROOT = "~";
 229
 230        const string KEYWORD_IT = "it";
 231        const string KEYWORD_PARENT = "parent";
 232        const string KEYWORD_ROOT = "root";
 233        const string KEYWORD_IIF = "iif";
 234        const string KEYWORD_NEW = "new";
 235        const string KEYWORD_ISNULL = "isnull";
 236
 1237        static readonly string methodOrderBy = nameof(Queryable.OrderBy);
 1238        static readonly string methodOrderByDescending = nameof(Queryable.OrderByDescending);
 1239        static readonly string methodThenBy = nameof(Queryable.ThenBy);
 1240        static readonly string methodThenByDescending = nameof(Queryable.ThenByDescending);
 241
 242        static Dictionary<string, object> _keywords;
 243
 244        readonly Dictionary<string, object> _symbols;
 245        IDictionary<string, object> _externals;
 246        readonly Dictionary<string, object> _internals;
 247        readonly Dictionary<Expression, string> _literals;
 248        ParameterExpression _it;
 249        ParameterExpression _parent;
 250        ParameterExpression _root;
 251
 252
 253
 254        static ExpressionParser()
 1255        {
 256#if !(NET35 || SILVERLIGHT || NETFX_CORE ||WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 257            //System.Data.Entity is always here, so overwrite short name of it with EntityFramework if EntityFramework i
 258            //EF5(or 4.x??), System.Data.Objects.DataClasses.EdmFunctionAttribute
 259            //There is also an System.Data.Entity, Version=3.5.0.0, but no Functions.
 260            UpdatePredefinedTypes("System.Data.Objects.EntityFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neu
 261            UpdatePredefinedTypes("System.Data.Objects.SqlClient.SqlFunctions, System.Data.Entity, Version=4.0.0.0, Cult
 262            UpdatePredefinedTypes("System.Data.Objects.SqlClient.SqlSpatialFunctions, System.Data.Entity, Version=4.0.0.
 263
 264            //EF6,System.Data.Entity.DbFunctionAttribute
 265            UpdatePredefinedTypes("System.Data.Entity.Core.Objects.EntityFunctions, EntityFramework, Version=6.0.0.0, Cu
 266            UpdatePredefinedTypes("System.Data.Entity.DbFunctions, EntityFramework, Version=6.0.0.0, Culture=neutral, Pu
 267            UpdatePredefinedTypes("System.Data.Entity.SqlServer.SqlFunctions, EntityFramework.SqlServer, Version=6.0.0.0
 268            UpdatePredefinedTypes("System.Data.Entity.SqlServer.SqlSpatialFunctions, EntityFramework.SqlServer, Version=
 269#endif
 270            // detect NumberDecimalSeparator from current culture
 271            //NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
 272            //NumberDecimalSeparatorFromCulture = numberFormatInfo.NumberDecimalSeparator[0];
 1273        }
 274
 275        private static void UpdatePredefinedTypes(string typeName, int x)
 0276        {
 277            try
 0278            {
 0279                Type efType = Type.GetType(typeName);
 0280                 if (efType != null)
 0281                    _predefinedTypes.Add(efType, x);
 0282            }
 0283            catch
 0284            {
 285                // in case of exception, do not add
 0286            }
 0287        }
 288        private readonly TextParser _textParser;
 289
 374290        public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values)
 374291        {
 374292             if (_keywords == null)
 13293                _keywords = CreateKeywords();
 27174                 if (_textParser.CurrentToken.Id != TokenId.Comma)
 23175                {
 23176                    break;
 177                }
 178
 4179                _textParser.NextToken();
 4180            }
 181
 23182            _textParser.ValidateToken(TokenId.End, Res.SyntaxError);
 23183            return orderings;
 23184        }
 185#pragma warning restore 0219
 186
 187        // ?: operator
 188        Expression ParseConditionalOperator()
 789189        {
 789190            int errorPos = _textParser.CurrentToken.Pos;
 789191            Expression expr = ParseNullCoalescingOperator();
 756192             if (_textParser.CurrentToken.Id == TokenId.Question)
 1193            {
 1194                _textParser.NextToken();
 1195                Expression expr1 = ParseConditionalOperator();
 1196                _textParser.ValidateToken(TokenId.Colon, Res.ColonExpected);
 1197                _textParser.NextToken();
 1198                Expression expr2 = ParseConditionalOperator();
 1199                expr = GenerateConditional(expr, expr1, expr2, errorPos);
 1200            }
 756201            return expr;
 756202        }
 203
 204        // ?. (null-propagating) operator
 205        //Expression ParseNullPropagatingOperator()
 206        //{
 207        //    int errorPos = _textParser.CurrentToken.Pos;
 208        //    Expression expr = ParseNullCoalescingOperator();
 209        //    if (_textParser.CurrentToken.Id == TokenId.Question)
 210        //    {
 211        //        _textParser.NextToken();
 212        //        Expression expr1 = ParseConditionalOperator();
 213        //        _textParser.ValidateToken(TokenId.Dot, Res.DotExpected);
 214        //        _textParser.NextToken();
 215        //        Expression expr2 = ParseConditionalOperator();
 216        //        expr = GenerateConditional(expr, expr1, expr2, errorPos);
 217        //    }
 218        //    return expr;
 219        //}
 220
 221        // ?? (null-coalescing) operator
 222        Expression ParseNullCoalescingOperator()
 789223        {
 789224            Expression expr = ParseLambdaOperator();
 756225             if (_textParser.CurrentToken.Id == TokenId.NullCoalescing)
 6226            {
 6227                _textParser.NextToken();
 6228                Expression right = ParseConditionalOperator();
 6229                expr = Expression.Coalesce(expr, right);
 6230            }
 756231            return expr;
 756232        }
 233
 234        // => operator - Added Support for projection operator
 235        Expression ParseLambdaOperator()
 789236        {
 789237            Expression expr = ParseOrOperator();
 756238             if (_textParser.CurrentToken.Id == TokenId.Lambda && _it.Type == expr.Type)
 0239            {
 0240                _textParser.NextToken();
 0241                 if (_textParser.CurrentToken.Id == TokenId.Identifier || _textParser.CurrentToken.Id == TokenId.OpenPare
 0242                {
 0243                    var right = ParseConditionalOperator();
 0244                    return Expression.Lambda(right, new[] { (ParameterExpression)expr });
 245                }
 0246                _textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
 0247            }
 756248            return expr;
 756249        }
 250
 251        // isnull(a,b) operator
 252        Expression ParseIsNull()
 6253        {
 6254            int errorPos = _textParser.CurrentToken.Pos;
 6255            _textParser.NextToken();
 6256            Expression[] args = ParseArgumentList();
 6257             if (args.Length != 2)
 1258            {
 1259                throw ParseError(errorPos, Res.IsNullRequiresTwoArgs);
 260            }
 261
 5262            return Expression.Coalesce(args[0], args[1]);
 5263        }
 264
 265        // ||, or operator
 266        Expression ParseOrOperator()
 789267        {
 789268            Expression left = ParseAndOperator();
 773269             while (_textParser.CurrentToken.Id == TokenId.DoubleBar || TokenIdentifierIs("or"))
 17270            {
 17271                Token op = _textParser.CurrentToken;
 17272                _textParser.NextToken();
 17273                Expression right = ParseAndOperator();
 17274                CheckAndPromoteOperands(typeof(ILogicalSignatures), op.Text, ref left, ref right, op.Pos);
 17275                left = Expression.OrElse(left, right);
 17276            }
 756277            return left;
 756278        }
 279
 280        // &&, and operator
 281        Expression ParseAndOperator()
 806282        {
 806283            Expression left = ParseIn();
 779284             while (_textParser.CurrentToken.Id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))
 6285            {
 6286                Token op = _textParser.CurrentToken;
 6287                _textParser.NextToken();
 6288                Expression right = ParseComparisonOperator();
 6289                CheckAndPromoteOperands(typeof(ILogicalSignatures), op.Text, ref left, ref right, op.Pos);
 6290                left = Expression.AndAlso(left, right);
 6291            }
 773292            return left;
 773293        }
 294
 374295            _symbols = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
 374296            _internals = new Dictionary<string, object>();
 374297            _literals = new Dictionary<Expression, string>();
 298
 374299             if (parameters != null)
 374300                ProcessParameters(parameters);
 301
 374302             if (values != null)
 364303                ProcessValues(values);
 304
 374305            _textParser = new TextParser(expression);
 374306        }
 307
 308        void ProcessParameters(ParameterExpression[] parameters)
 374309        {
 1874310            foreach (ParameterExpression pe in parameters)
 376311                 if (!string.IsNullOrEmpty(pe.Name))
 18312                    AddSymbol(pe.Name, pe);
 374313             if (parameters.Length == 1 && string.IsNullOrEmpty(parameters[0].Name))
 358314            {
 358315                _parent = _it;
 358316                _it = parameters[0];
 358317                 if (_root == null)
 358318                    _root = _it;
 358319            }
 374320        }
 321
 322        void ProcessValues(object[] values)
 364323        {
 900324             for (int i = 0; i < values.Length; i++)
 86325            {
 86326                object value = values[i];
 327                IDictionary<string, object> externals;
 295        // in operator for literals - example: "x in (1,2,3,4)"
 296        // in operator to mimic contains - example: "x in @0", compare to @0.Contains(x)
 297        // Adapted from ticket submitted by github user mlewis9548
 298        Expression ParseIn()
 806299        {
 806300            Expression left = ParseLogicalAndOrOperator();
 777301            Expression accumulate = left;
 302
 791303             while (TokenIdentifierIs("in"))
 18304            {
 18305                var op = _textParser.CurrentToken;
 306
 18307                _textParser.NextToken();
 18308                 if (_textParser.CurrentToken.Id == TokenId.OpenParen) // literals (or other inline list)
 15309                {
 44310                     while (_textParser.CurrentToken.Id != TokenId.CloseParen)
 33311                    {
 33312                        _textParser.NextToken();
 313
 314                        // we need to parse unary expressions because otherwise 'in' clause will fail in use cases like 
 30315                        Expression right = ParseUnary();
 316
 317                        // if the identifier is an Enum, try to convert the right-side also to an Enum.
 29318                         if (left.Type.GetTypeInfo().IsEnum && right is ConstantExpression)
 4319                        {
 4320                            right = ParseEnumToConstantExpression(op.Pos, left.Type, right as ConstantExpression);
 4321                        }
 322
 323                        // else, check for direct type match
 25324                         else if (left.Type != right.Type)
 2325                        {
 2326                            CheckAndPromoteOperands(typeof(IEqualitySignatures), "==", ref left, ref right, op.Pos);
 2327                        }
 328
 86329                 if (i == values.Length - 1 && (externals = value as IDictionary<string, object>) != null)
 3330                {
 3331                    _externals = externals;
 3332                }
 333                else
 83334                {
 83335                    AddSymbol("@" + i.ToString(CultureInfo.InvariantCulture), value);
 83336                }
 86337            }
 364338        }
 339
 340        void AddSymbol(string name, object value)
 101341        {
 101342             if (_symbols.ContainsKey(name))
 0343                throw ParseError(Res.DuplicateIdentifier, name);
 101344            _symbols.Add(name, value);
 101345        }
 346
 347        private Type _resultType;
 348        private bool _createParameterCtor;
 349        public Expression Parse(Type resultType, bool createParameterCtor)
 351350        {
 351351            _resultType = resultType;
 351352            _createParameterCtor = createParameterCtor;
 353
 351354            int exprPos = _textParser.CurrentToken.Pos;
 351355            Expression expr = ParseConditionalOperator();
 356
 323357             if (resultType != null)
 176358            {
 176359                 if ((expr = PromoteExpression(expr, resultType, true, false)) == null)
 1360                {
 1361                    throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType));
 362                }
 175363            }
 364
 322365            _textParser.ValidateToken(TokenId.End, Res.SyntaxError);
 366
 318367            return expr;
 318368        }
 369
 370#pragma warning disable 0219
 371        public IList<DynamicOrdering> ParseOrdering(bool forceThenBy = false)
 23372        {
 23373            var orderings = new List<DynamicOrdering>();
 27374            while (true)
 27375            {
 27376                Expression expr = ParseConditionalOperator();
 25377                bool ascending = true;
 25378                 if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending"))
 1379                {
 1380                    _textParser.NextToken();
 1381                }
 24382                 else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending"))
 4383                {
 4384                    _textParser.NextToken();
 4385                    ascending = false;
 4386                }
 387
 388                string methodName;
 25389                 if (forceThenBy || orderings.Count > 0)
 6390                     methodName = ascending ? methodThenBy : methodThenByDescending;
 391                else
 19392                     methodName = ascending ? methodOrderBy : methodOrderByDescending;
 393
 25394                orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending, MethodName = methodName });
 395
 25396                 if (_textParser.CurrentToken.Id != TokenId.Comma)
 21397                    break;
 398
 4399                _textParser.NextToken();
 4400            }
 401
 21402            _textParser.ValidateToken(TokenId.End, Res.SyntaxError);
 21403            return orderings;
 21404        }
 405#pragma warning restore 0219
 406
 407        // ?: operator
 408        Expression ParseConditionalOperator()
 578409        {
 578410            int errorPos = _textParser.CurrentToken.Pos;
 578411            Expression expr = ParseNullCoalescingOperator();
 546412             if (_textParser.CurrentToken.Id == TokenId.Question)
 1413            {
 1414                _textParser.NextToken();
 1415                Expression expr1 = ParseConditionalOperator();
 1416                _textParser.ValidateToken(TokenId.Colon, Res.ColonExpected);
 1417                _textParser.NextToken();
 1418                Expression expr2 = ParseConditionalOperator();
 1419                expr = GenerateConditional(expr, expr1, expr2, errorPos);
 1420            }
 546421            return expr;
 546422        }
 423
 424        // ?? (null-coalescing) operator
 425        Expression ParseNullCoalescingOperator()
 578426        {
 578427            Expression expr = ParseLambdaOperator();
 546428             if (_textParser.CurrentToken.Id == TokenId.NullCoalescing)
 6429            {
 6430                _textParser.NextToken();
 6431                Expression right = ParseConditionalOperator();
 6432                expr = Expression.Coalesce(expr, right);
 6433            }
 546434            return expr;
 546435        }
 436
 437        // => operator - Added Support for projection operator
 438        Expression ParseLambdaOperator()
 578439        {
 578440            Expression expr = ParseOrOperator();
 546441             if (_textParser.CurrentToken.Id == TokenId.Lambda && _it.Type == expr.Type)
 0442            {
 0443                _textParser.NextToken();
 0444                 if (_textParser.CurrentToken.Id == TokenId.Identifier ||
 0445                    _textParser.CurrentToken.Id == TokenId.OpenParen)
 0446                {
 0447                    var right = ParseConditionalOperator();
 0448                    return Expression.Lambda(right, new[] { (ParameterExpression)expr });
 449                }
 0450                _textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
 0451            }
 546452            return expr;
 546453        }
 454
 455        // isnull(a,b) operator
 456        Expression ParseIsNull()
 6457        {
 6458            int errorPos = _textParser.CurrentToken.Pos;
 6459            _textParser.NextToken();
 6460            Expression[] args = ParseArgumentList();
 6461             if (args.Length != 2)
 1462                throw ParseError(errorPos, Res.IsNullRequiresTwoArgs);
 463
 5464            return Expression.Coalesce(args[0], args[1]);
 5465        }
 466
 467        // ||, or operator
 468        Expression ParseOrOperator()
 578469        {
 578470            Expression left = ParseAndOperator();
 559471             while (_textParser.CurrentToken.Id == TokenId.DoubleBar || TokenIdentifierIs("or"))
 13472            {
 13473                Token op = _textParser.CurrentToken;
 13474                _textParser.NextToken();
 13475                Expression right = ParseAndOperator();
 13476                CheckAndPromoteOperands(typeof(ILogicalSignatures), op.Text, ref left, ref right, op.Pos);
 13477                left = Expression.OrElse(left, right);
 13478            }
 546479            return left;
 546480        }
 481
 482        // &&, and operator
 483        Expression ParseAndOperator()
 591484        {
 591485            Expression left = ParseIn();
 565486             while (_textParser.CurrentToken.Id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))
 6487            {
 6488                Token op = _textParser.CurrentToken;
 6489                _textParser.NextToken();
 6490                Expression right = ParseComparisonOperator();
 6491                CheckAndPromoteOperands(typeof(ILogicalSignatures), op.Text, ref left, ref right, op.Pos);
 6492                left = Expression.AndAlso(left, right);
 6493            }
 559494            return left;
 559495        }
 496
 497        // in operator for literals - example: "x in (1,2,3,4)"
 498        // in operator to mimic contains - example: "x in @0", compare to @0.Contains(x)
 499        // Adapted from ticket submitted by github user mlewis9548
 500        Expression ParseIn()
 591501        {
 591502            Expression left = ParseLogicalAndOrOperator();
 563503            Expression accumulate = left;
 504
 576505             while (TokenIdentifierIs("in"))
 17506            {
 17507                var op = _textParser.CurrentToken;
 508
 17509                _textParser.NextToken();
 17510                 if (_textParser.CurrentToken.Id == TokenId.OpenParen) //literals (or other inline list)
 14511                {
 40512                     while (_textParser.CurrentToken.Id != TokenId.CloseParen)
 30513                    {
 30514                        _textParser.NextToken();
 515
 516                        //we need to parse unary expressions because otherwise 'in' clause will fail in use cases like '
 27517                        Expression right = ParseUnary();
 29329                         if (accumulate.Type != typeof(bool))
 12330                        {
 12331                            accumulate = ExpressionHelper.GenerateEqual(left, right);
 12332                        }
 333                        else
 17334                        {
 17335                            accumulate = Expression.OrElse(accumulate, ExpressionHelper.GenerateEqual(left, right));
 17336                        }
 337
 29338                         if (_textParser.CurrentToken.Id == TokenId.End)
 0339                        {
 0340                            throw ParseError(op.Pos, Res.CloseParenOrCommaExpected);
 341                        }
 29342                    }
 11343                }
 3344                 else if (_textParser.CurrentToken.Id == TokenId.Identifier) // a single argument
 3345                {
 3346                    Expression right = ParsePrimary();
 347
 3348                     if (!typeof(IEnumerable).IsAssignableFrom(right.Type))
 0349                    {
 0350                        throw ParseError(_textParser.CurrentToken.Pos, Res.IdentifierImplementingInterfaceExpected, type
 351                    }
 352
 3353                    var args = new[] { left };
 354
 3355                     if (MethodFinder.FindMethod(typeof(IEnumerableSignatures), nameof(IEnumerableSignatures.Contains), f
 0356                    {
 0357                        throw ParseError(op.Pos, Res.NoApplicableAggregate, nameof(IEnumerableSignatures.Contains));
 358                    }
 359
 3360                    var typeArgs = new[] { left.Type };
 361
 3362                    args = new[] { right, left };
 363
 3364                    accumulate = Expression.Call(typeof(Enumerable), containsSignature.Name, typeArgs, args);
 3365                }
 366                else
 0367                {
 0368                    throw ParseError(op.Pos, Res.OpenParenOrIdentifierExpected);
 369                }
 370
 14371                _textParser.NextToken();
 14372            }
 373
 773374            return accumulate;
 773375        }
 376
 377        // &, | bitwise operators
 378        Expression ParseLogicalAndOrOperator()
 806379        {
 806380            Expression left = ParseComparisonOperator();
 819381             while (_textParser.CurrentToken.Id == TokenId.Amphersand || _textParser.CurrentToken.Id == TokenId.Bar)
 42382            {
 42383                Token op = _textParser.CurrentToken;
 42384                _textParser.NextToken();
 42385                Expression right = ParseComparisonOperator();
 386
 42387                 if (left.Type.GetTypeInfo().IsEnum)
 32388                {
 32389                    left = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
 32390                }
 391
 42392                 if (right.Type.GetTypeInfo().IsEnum)
 0393                {
 0394                    right = Expression.Convert(right, Enum.GetUnderlyingType(right.Type));
 0395                }
 396
 42397                 switch (op.Id)
 398                {
 399                    case TokenId.Amphersand:
 400                        int parseValue;
 26401                         if (left.Type == typeof(string) && left.NodeType == ExpressionType.Constant && int.TryParse((str
 1402                        {
 1403                            left = Expression.Constant(parseValue);
 1404                        }
 25405                         else if (right.Type == typeof(string) && right.NodeType == ExpressionType.Constant && int.TryPar
 2406                        {
 2407                            right = Expression.Constant(parseValue);
 2408                        }
 409
 410                        // When at least one side of the operator is a string, consider it's a VB-style concatenation op
 411                        // Doesn't break any other function since logical AND with a string is invalid anyway.
 26412                         if (left.Type == typeof(string) || right.Type == typeof(string))
 5413                        {
 5414                            left = ExpressionHelper.GenerateStringConcat(left, right);
 5415                        }
 416                        else
 21417                        {
 21418                            ExpressionHelper.ConvertNumericTypeToBiggestCommonTypeForBinaryOperator(ref left, ref right)
 21419                            left = Expression.And(left, right);
 21420                        }
 26421                        break;
 422
 423                    case TokenId.Bar:
 16424                        ExpressionHelper.ConvertNumericTypeToBiggestCommonTypeForBinaryOperator(ref left, ref right);
 16425                        left = Expression.Or(left, right);
 16426                        break;
 427                }
 42428            }
 777429            return left;
 777430        }
 431
 432        // =, ==, !=, <>, >, >=, <, <= operators
 433        Expression ParseComparisonOperator()
 854434        {
 854435            Expression left = ParseShiftOperator();
 1070436             while (_textParser.CurrentToken.Id == TokenId.Equal || _textParser.CurrentToken.Id == TokenId.DoubleEqual ||
 1070437                   _textParser.CurrentToken.Id == TokenId.ExclamationEqual || _textParser.CurrentToken.Id == TokenId.Les
 1070438                   _textParser.CurrentToken.Id == TokenId.GreaterThan || _textParser.CurrentToken.Id == TokenId.GreaterT
 1070439                   _textParser.CurrentToken.Id == TokenId.LessThan || _textParser.CurrentToken.Id == TokenId.LessThanEqu
 245440            {
 441                ConstantExpression constantExpr;
 442                TypeConverter typeConverter;
 245443                Token op = _textParser.CurrentToken;
 245444                _textParser.NextToken();
 243445                Expression right = ParseShiftOperator();
 239446                bool isEquality = op.Id == TokenId.Equal || op.Id == TokenId.DoubleEqual || op.Id == TokenId.Exclamation
 447
 239448                 if (isEquality && (!left.Type.GetTypeInfo().IsValueType && !right.Type.GetTypeInfo().IsValueType || left
 33449                {
 450                    // If left or right is NullLiteral, just continue. Else check if the types differ.
 33451                     if (!(left == Constants.NullLiteral || right == Constants.NullLiteral) && left.Type != right.Type)
 0452                    {
 0453                         if (left.Type.IsAssignableFrom(right.Type))
 0454                        {
 0455                            right = Expression.Convert(right, left.Type);
 0456                        }
 0457                         else if (right.Type.IsAssignableFrom(left.Type))
 0458                        {
 0459                            left = Expression.Convert(left, right.Type);
 0460                        }
 461                        else
 0462                        {
 0463                            throw IncompatibleOperandsError(op.Text, left, right, op.Pos);
 464                        }
 0465                    }
 33466                }
 206467                 else if (TypeHelper.IsEnumType(left.Type) || TypeHelper.IsEnumType(right.Type))
 33468                {
 33469                     if (left.Type != right.Type)
 17470                    {
 471                        Expression e;
 17472                         if ((e = ExpressionPromoter.Promote(right, left.Type, true, false)) != null)
 2473                        {
 2474                            right = e;
 2475                        }
 15476                         else if ((e = ExpressionPromoter.Promote(left, right.Type, true, false)) != null)
 2477                        {
 2478                            left = e;
 2479                        }
 13480                         else if (TypeHelper.IsEnumType(left.Type) && (constantExpr = right as ConstantExpression) != nul
 6481                        {
 6482                            right = ParseEnumToConstantExpression(op.Pos, left.Type, constantExpr);
 6483                        }
 7484                         else if (TypeHelper.IsEnumType(right.Type) && (constantExpr = left as ConstantExpression) != nul
 7485                        {
 7486                            left = ParseEnumToConstantExpression(op.Pos, right.Type, constantExpr);
 7487                        }
 488                        else
 0489                        {
 0490                            throw IncompatibleOperandsError(op.Text, left, right, op.Pos);
 491                        }
 17492                    }
 33493                }
 173494                 else if ((constantExpr = right as ConstantExpression) != null && constantExpr.Value is string && (typeCo
 7495                {
 7496                    right = Expression.Constant(typeConverter.ConvertFromInvariantString((string)constantExpr.Value), le
 7497                }
 166498                 else if ((constantExpr = left as ConstantExpression) != null && constantExpr.Value is string && (typeCon
 3499                {
 3500                    left = Expression.Constant(typeConverter.ConvertFromInvariantString((string)constantExpr.Value), rig
 3501                }
 502                else
 163503                {
 163504                    bool typesAreSameAndImplementCorrectInterface = false;
 163505                     if (left.Type == right.Type)
 104506                    {
 572507                        var interfaces = left.Type.GetInterfaces().Where(x => x.GetTypeInfo().IsGenericType);
 104508                         if (isEquality)
 61509                        {
 183510                            typesAreSameAndImplementCorrectInterface = interfaces.Any(x => x.GetGenericTypeDefinition() 
 61511                        }
 512                        else
 43513                        {
 86514                            typesAreSameAndImplementCorrectInterface = interfaces.Any(x => x.GetGenericTypeDefinition() 
 43515                        }
 104516                    }
 517
 518
 519                        // if the identifier is an Enum, try to convert the right-side also to an Enum.
 27520                         if (left.Type.GetTypeInfo().IsEnum && right is ConstantExpression)
 4521                        {
 4522                            right = ParseEnumToConstantExpression(op.Pos, left.Type, right as ConstantExpression);
 4523                        }
 524
 525                        // else, check for direct type match
 23526                         else if (left.Type != right.Type)
 1527                        {
 528                            //check for nullable type match
 1529                             if (!left.Type.GetTypeInfo().IsGenericType ||
 1530                                left.Type.GetGenericTypeDefinition() != typeof(Nullable<>) ||
 1531                                left.Type.GetTypeInfo().GetGenericTypeArguments()[0] != right.Type)
 1532                            {
 1533                                throw ParseError(op.Pos, Res.ExpressionTypeMismatch, left.Type);
 534                            }
 163519                     if (!typesAreSameAndImplementCorrectInterface)
 59520                    {
 59521                         if (left.Type.GetTypeInfo().IsClass && right is ConstantExpression && HasImplicitConversion(left
 1522                        {
 1523                            left = Expression.Convert(left, right.Type);
 1524                        }
 58525                         else if (right.Type.GetTypeInfo().IsClass && left is ConstantExpression && HasImplicitConversion
 1526                        {
 1527                            right = Expression.Convert(right, left.Type);
 1528                        }
 529                        else
 57530                        {
 57531                             CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatu
 54532                        }
 56533                    }
 160534                }
 535
 0536                            CheckAndPromoteOperands(typeof(IEqualitySignatures), "==", ref left, ref right, op.Pos);
 0537                        }
 538
 26539                         if (accumulate.Type != typeof(bool))
 10540                        {
 10541                            accumulate = GenerateEqual(left, right);
 10542                        }
 543                        else
 16544                        {
 16545                            accumulate = Expression.OrElse(accumulate, GenerateEqual(left, right));
 16546                        }
 547
 26548                         if (_textParser.CurrentToken.Id == TokenId.End)
 0549                            throw ParseError(op.Pos, Res.CloseParenOrCommaExpected);
 26550                    }
 10551                }
 3552                 else if (_textParser.CurrentToken.Id == TokenId.Identifier) //a single argument
 3553                {
 3554                    Expression right = ParsePrimary();
 555
 3556                     if (!typeof(IEnumerable).IsAssignableFrom(right.Type))
 0557                        throw ParseError(_textParser.CurrentToken.Pos, Res.IdentifierImplementingInterfaceExpected, type
 558
 3559                    var args = new[] { left };
 236536                 switch (op.Id)
 537                {
 538                    case TokenId.Equal:
 539                    case TokenId.DoubleEqual:
 172540                        left = ExpressionHelper.GenerateEqual(left, right);
 172541                        break;
 542                    case TokenId.ExclamationEqual:
 543                    case TokenId.LessGreater:
 7544                        left = ExpressionHelper.GenerateNotEqual(left, right);
 7545                        break;
 546                    case TokenId.GreaterThan:
 42547                        left = ExpressionHelper.GenerateGreaterThan(left, right);
 42548                        break;
 549                    case TokenId.GreaterThanEqual:
 3550                        left = ExpressionHelper.GenerateGreaterThanEqual(left, right);
 3551                        break;
 552                    case TokenId.LessThan:
 8553                        left = ExpressionHelper.GenerateLessThan(left, right);
 8554                        break;
 555                    case TokenId.LessThanEqual:
 4556                        left = ExpressionHelper.GenerateLessThanEqual(left, right);
 4557                        break;
 558                }
 236559            }
 560
 561                    MethodBase containsSignature;
 3562                     if (FindMethod(typeof(IEnumerableSignatures), "Contains", false, args, out containsSignature) != 1)
 0563                        throw ParseError(op.Pos, Res.NoApplicableAggregate, "Contains");
 564
 3565                    var typeArgs = new[] { left.Type };
 3566                    args = new[] { right, left };
 567
 3568                    accumulate = Expression.Call(typeof(Enumerable), containsSignature.Name, typeArgs, args);
 3569                }
 570                else
 0571                    throw ParseError(op.Pos, Res.OpenParenOrIdentifierExpected);
 572
 13573                _textParser.NextToken();
 13574            }
 825561            return left;
 825562        }
 563
 564        private bool HasImplicitConversion(Type baseType, Type targetType)
 2565        {
 2566            return baseType.GetMethods(BindingFlags.Public | BindingFlags.Static)
 4567                .Where(mi => mi.Name == "op_Implicit" && mi.ReturnType == targetType)
 4568                 .Any(mi => mi.GetParameters().FirstOrDefault()?.ParameterType == baseType);
 2569        }
 570
 571        private ConstantExpression ParseEnumToConstantExpression(int pos, Type leftType, ConstantExpression constantExpr
 17572        {
 17573            return Expression.Constant(ParseConstantExpressionToEnum(pos, leftType, constantExpr), leftType);
 17574        }
 575
 559576            return accumulate;
 559577        }
 578
 579        // &, | bitwise operators
 580        Expression ParseLogicalAndOrOperator()
 591581        {
 591582            Expression left = ParseComparisonOperator();
 570583             while (_textParser.CurrentToken.Id == TokenId.Amphersand || _textParser.CurrentToken.Id == TokenId.Bar)
 7584            {
 7585                Token op = _textParser.CurrentToken;
 7586                _textParser.NextToken();
 7587                Expression right = ParseComparisonOperator();
 588
 7589                 if (left.Type.GetTypeInfo().IsEnum)
 0590                {
 0591                    left = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
 0592                }
 593
 7594                 if (right.Type.GetTypeInfo().IsEnum)
 0595                {
 0596                    right = Expression.Convert(right, Enum.GetUnderlyingType(right.Type));
 0597                }
 598
 7599                 switch (op.Id)
 600                {
 601                    case TokenId.Amphersand:
 602                        // When at least one side of the operator is a string, consider it's a VB-style concatenation op
 603                        // Doesn't break any other function since logical AND with a string is invalid anyway.
 7604                         if (left.Type == typeof(string) || right.Type == typeof(string))
 5605                        {
 5606                            left = GenerateStringConcat(left, right);
 5607                        }
 608                        else
 2609                        {
 2610                            left = Expression.And(left, right);
 2611                        }
 7612                        break;
 613
 614                    case TokenId.Bar:
 0615                        left = Expression.Or(left, right);
 0616                        break;
 617                }
 7618            }
 563619            return left;
 563620        }
 621
 622        // =, ==, !=, <>, >, >=, <, <= operators
 623        Expression ParseComparisonOperator()
 604624        {
 604625            Expression left = ParseShiftOperator();
 748626             while (_textParser.CurrentToken.Id == TokenId.Equal || _textParser.CurrentToken.Id == TokenId.DoubleEqual ||
 748627                   _textParser.CurrentToken.Id == TokenId.ExclamationEqual || _textParser.CurrentToken.Id == TokenId.Les
 748628                   _textParser.CurrentToken.Id == TokenId.GreaterThan || _textParser.CurrentToken.Id == TokenId.GreaterT
 748629                   _textParser.CurrentToken.Id == TokenId.LessThan || _textParser.CurrentToken.Id == TokenId.LessThanEqu
 172630            {
 631                ConstantExpression constantExpr;
 632                TypeConverter typeConverter;
 172633                Token op = _textParser.CurrentToken;
 172634                _textParser.NextToken();
 170635                Expression right = ParseShiftOperator();
 166636                bool isEquality = op.Id == TokenId.Equal || op.Id == TokenId.DoubleEqual || op.Id == TokenId.Exclamation
 637
 166638                 if (isEquality && (!left.Type.GetTypeInfo().IsValueType && !right.Type.GetTypeInfo().IsValueType || left
 25639                {
 25640                     if (left.Type != right.Type)
 5641                    {
 5642                         if (left.Type.IsAssignableFrom(right.Type))
 0643                        {
 0644                            right = Expression.Convert(right, left.Type);
 0645                        }
 5646                         else if (right.Type.IsAssignableFrom(left.Type))
 5647                        {
 5648                            left = Expression.Convert(left, right.Type);
 5649                        }
 650                        else
 0651                        {
 0652                            throw IncompatibleOperandsError(op.Text, left, right, op.Pos);
 653                        }
 5654                    }
 25655                }
 141656                 else if (IsEnumType(left.Type) || IsEnumType(right.Type))
 24657                {
 24658                     if (left.Type != right.Type)
 14659                    {
 660                        Expression e;
 14661                         if ((e = PromoteExpression(right, left.Type, true, false)) != null)
 2662                        {
 2663                            right = e;
 2664                        }
 12665                         else if ((e = PromoteExpression(left, right.Type, true, false)) != null)
 2666                        {
 2667                            left = e;
 2668                        }
 10669                         else if (IsEnumType(left.Type) && (constantExpr = right as ConstantExpression) != null)
 5670                        {
 5671                            right = ParseEnumToConstantExpression(op.Pos, left.Type, constantExpr);
 5672                        }
 5673                         else if (IsEnumType(right.Type) && (constantExpr = left as ConstantExpression) != null)
 5674                        {
 5675                            left = ParseEnumToConstantExpression(op.Pos, right.Type, constantExpr);
 5676                        }
 677                        else
 0678                        {
 0679                            throw IncompatibleOperandsError(op.Text, left, right, op.Pos);
 680                        }
 14681                    }
 24682                }
 117683                 else if ((constantExpr = right as ConstantExpression) != null && constantExpr.Value is string && (typeCo
 7684                {
 7685                    right = Expression.Constant(typeConverter.ConvertFromInvariantString((string)constantExpr.Value), le
 7686                }
 110687                 else if ((constantExpr = left as ConstantExpression) != null && constantExpr.Value is string && (typeCon
 3688                {
 3689                    left = Expression.Constant(typeConverter.ConvertFromInvariantString((string)constantExpr.Value), rig
 3690                }
 691                else
 107692                {
 107693                     CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures),
 107694                        op.Text, ref left, ref right, op.Pos);
 104695                }
 696
 163697                 switch (op.Id)
 698                {
 699                    case TokenId.Equal:
 700                    case TokenId.DoubleEqual:
 107701                        left = GenerateEqual(left, right);
 107702                        break;
 703                    case TokenId.ExclamationEqual:
 704                    case TokenId.LessGreater:
 6705                        left = GenerateNotEqual(left, right);
 6706                        break;
 707                    case TokenId.GreaterThan:
 38708                        left = GenerateGreaterThan(left, right);
 38709                        break;
 710                    case TokenId.GreaterThanEqual:
 3711                        left = GenerateGreaterThanEqual(left, right);
 3712                        break;
 713                    case TokenId.LessThan:
 5714                        left = GenerateLessThan(left, right);
 5715                        break;
 716                    case TokenId.LessThanEqual:
 4717                        left = GenerateLessThanEqual(left, right);
 4718                        break;
 719                }
 163720            }
 721
 576722            return left;
 576723        }
 724
 725        private ConstantExpression ParseEnumToConstantExpression(int pos, Type leftType, ConstantExpression constantExpr
 14726        {
 14727            return Expression.Constant(ParseConstantExpressionToEnum(pos, leftType, constantExpr), leftType);
 14728        }
 729
 730        private object ParseConstantExpressionToEnum(int pos, Type leftType, ConstantExpression constantExpr)
 14731        {
 14732            object parsedEnum = null;
 733            try
 14734            {
 14735                 if (constantExpr.Value is string)
 10736                {
 10737                    return parsedEnum = Enum.Parse(GetNonNullableType(leftType), constantExpr.Value as string, true);
 738                }
 739                else
 4740                {
 4741                    return parsedEnum = Enum.ToObject(leftType, constantExpr.Value);
 742                }
 743            }
 0744            catch
 0745            {
 0746                throw ParseError(pos, Res.ExpressionTypeMismatch, leftType);
 747            }
 14748        }
 749
 750        // <<, >> operators
 751        Expression ParseShiftOperator()
 774752        {
 774753            Expression left = ParseAdditive();
 783754             while (_textParser.CurrentToken.Id == TokenId.DoubleLessThan || _textParser.CurrentToken.Id == TokenId.Doubl
 32755            {
 32756                Token op = _textParser.CurrentToken;
 32757                _textParser.NextToken();
 32758                Expression right = ParseAdditive();
 32759                 switch (op.Id)
 760                {
 761                    case TokenId.DoubleLessThan:
 24762                        CheckAndPromoteOperands(typeof(IShiftSignatures), op.Text, ref left, ref right, op.Pos);
 24763                        left = Expression.LeftShift(left, right);
 24764                        break;
 765                    case TokenId.DoubleGreaterThan:
 8766                        CheckAndPromoteOperands(typeof(IShiftSignatures), op.Text, ref left, ref right, op.Pos);
 8767                        left = Expression.RightShift(left, right);
 8768                        break;
 769                }
 32770            }
 751771            return left;
 751772        }
 773
 774        // +, - operators
 775        Expression ParseAdditive()
 806776        {
 806777            Expression left = ParseMultiplicative();
 799778             while (_textParser.CurrentToken.Id == TokenId.Plus || _textParser.CurrentToken.Id == TokenId.Minus)
 16779            {
 16780                Token op = _textParser.CurrentToken;
 16781                _textParser.NextToken();
 16782                Expression right = ParseMultiplicative();
 16783                 switch (op.Id)
 784                {
 785                    case TokenId.Plus:
 16786                         if (left.Type == typeof(string) || right.Type == typeof(string))
 5787                        {
 5788                            left = GenerateStringConcat(left, right);
 5789                        }
 790                        else
 11791                        {
 11792                            CheckAndPromoteOperands(typeof(IAddSignatures), op.Text, ref left, ref right, op.Pos);
 11793                            left = GenerateAdd(left, right);
 11794                        }
 16795                        break;
 796                    case TokenId.Minus:
 0797                        CheckAndPromoteOperands(typeof(ISubtractSignatures), op.Text, ref left, ref right, op.Pos);
 0798                        left = GenerateSubtract(left, right);
 0799                        break;
 800                }
 16801            }
 783802            return left;
 783803        }
 804
 805        // *, /, %, mod operators
 806        Expression ParseMultiplicative()
 822807        {
 822808            Expression left = ParseUnary();
 814809             while (_textParser.CurrentToken.Id == TokenId.Asterisk || _textParser.CurrentToken.Id == TokenId.Slash ||
 814810                _textParser.CurrentToken.Id == TokenId.Percent || TokenIdentifierIs("mod"))
 15811            {
 15812                Token op = _textParser.CurrentToken;
 15813                _textParser.NextToken();
 15814                Expression right = ParseUnary();
 15815                CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.Text, ref left, ref right, op.Pos);
 14816                 switch (op.Id)
 817                {
 818                    case TokenId.Asterisk:
 14819                        left = Expression.Multiply(left, right);
 14820                        break;
 821                    case TokenId.Slash:
 0822                        left = Expression.Divide(left, right);
 0823                        break;
 824                    case TokenId.Percent:
 825                    case TokenId.Identifier:
 0826                        left = Expression.Modulo(left, right);
 0827                        break;
 828                }
 14829            }
 799830            return left;
 799831        }
 832
 833        // -, !, not unary operators
 834        Expression ParseUnary()
 864835        {
 864836             if (_textParser.CurrentToken.Id == TokenId.Minus || _textParser.CurrentToken.Id == TokenId.Exclamation || To
 22837            {
 22838                Token op = _textParser.CurrentToken;
 22839                _textParser.NextToken();
 19840                 if (op.Id == TokenId.Minus && (_textParser.CurrentToken.Id == TokenId.IntegerLiteral || _textParser.Curr
 19841                {
 19842                    _textParser.CurrentToken.Text = "-" + _textParser.CurrentToken.Text;
 19843                    _textParser.CurrentToken.Pos = op.Pos;
 19844                    return ParsePrimary();
 845                }
 846
 0847                Expression expr = ParseUnary();
 0848                 if (op.Id == TokenId.Minus)
 0849                {
 0850                    CheckAndPromoteOperand(typeof(INegationSignatures), op.Text, ref expr, op.Pos);
 0851                    expr = Expression.Negate(expr);
 0852                }
 853                else
 0854                {
 0855                    CheckAndPromoteOperand(typeof(INotSignatures), op.Text, ref expr, op.Pos);
 0856                    expr = Expression.Not(expr);
 0857                }
 858
 0859                return expr;
 860            }
 861
 842862            return ParsePrimary();
 842863        }
 576        private object ParseConstantExpressionToEnum(int pos, Type leftType, ConstantExpression constantExpr)
 17577        {
 578            try
 17579            {
 17580                 if (constantExpr.Value is string)
 12581                {
 12582                    return Enum.Parse(TypeHelper.GetNonNullableType(leftType), (string)constantExpr.Value, true);
 583                }
 584
 5585                return Enum.ToObject(leftType, constantExpr.Value);
 586            }
 0587            catch
 0588            {
 0589                throw ParseError(pos, Res.ExpressionTypeMismatch, leftType);
 590            }
 17591        }
 592
 593        // <<, >> operators
 594        Expression ParseShiftOperator()
 1097595        {
 1097596            Expression left = ParseAdditive();
 1106597             while (_textParser.CurrentToken.Id == TokenId.DoubleLessThan || _textParser.CurrentToken.Id == TokenId.Doubl
 33598            {
 33599                Token op = _textParser.CurrentToken;
 33600                _textParser.NextToken();
 33601                Expression right = ParseAdditive();
 32602                 switch (op.Id)
 603                {
 604                    case TokenId.DoubleLessThan:
 24605                        CheckAndPromoteOperands(typeof(IShiftSignatures), op.Text, ref left, ref right, op.Pos);
 24606                        left = Expression.LeftShift(left, right);
 24607                        break;
 608                    case TokenId.DoubleGreaterThan:
 8609                        CheckAndPromoteOperands(typeof(IShiftSignatures), op.Text, ref left, ref right, op.Pos);
 8610                        left = Expression.RightShift(left, right);
 8611                        break;
 612                }
 32613            }
 1073614            return left;
 1073615        }
 616
 617        // +, - operators
 618        Expression ParseAdditive()
 1130619        {
 1130620            Expression left = ParseMultiplicative();
 1130621             while (_textParser.CurrentToken.Id == TokenId.Plus || _textParser.CurrentToken.Id == TokenId.Minus)
 24622            {
 24623                Token op = _textParser.CurrentToken;
 24624                _textParser.NextToken();
 24625                Expression right = ParseMultiplicative();
 24626                 switch (op.Id)
 627                {
 628                    case TokenId.Plus:
 23629                         if (left.Type == typeof(string) || right.Type == typeof(string))
 9630                        {
 9631                            left = ExpressionHelper.GenerateStringConcat(left, right);
 9632                        }
 633                        else
 14634                        {
 14635                            CheckAndPromoteOperands(typeof(IAddSignatures), op.Text, ref left, ref right, op.Pos);
 14636                            left = ExpressionHelper.GenerateAdd(left, right);
 14637                        }
 23638                        break;
 639                    case TokenId.Minus:
 1640                        CheckAndPromoteOperands(typeof(ISubtractSignatures), op.Text, ref left, ref right, op.Pos);
 1641                        left = ExpressionHelper.GenerateSubtract(left, right);
 1642                        break;
 643                }
 24644            }
 1106645            return left;
 1106646        }
 647
 648        // *, /, %, mod operators
 649        Expression ParseMultiplicative()
 1154650        {
 1154651            Expression left = ParseUnary();
 1148652             while (_textParser.CurrentToken.Id == TokenId.Asterisk || _textParser.CurrentToken.Id == TokenId.Slash ||
 1148653                _textParser.CurrentToken.Id == TokenId.Percent || TokenIdentifierIs("mod"))
 18654            {
 18655                Token op = _textParser.CurrentToken;
 18656                _textParser.NextToken();
 18657                Expression right = ParseUnary();
 18658                CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.Text, ref left, ref right, op.Pos);
 17659                 switch (op.Id)
 660                {
 661                    case TokenId.Asterisk:
 15662                        left = Expression.Multiply(left, right);
 15663                        break;
 664                    case TokenId.Slash:
 1665                        left = Expression.Divide(left, right);
 1666                        break;
 667                    case TokenId.Percent:
 668                    case TokenId.Identifier:
 1669                        left = Expression.Modulo(left, right);
 1670                        break;
 671                }
 17672            }
 1130673            return left;
 1130674        }
 675
 676        // -, !, not unary operators
 677        Expression ParseUnary()
 1202678        {
 1202679             if (_textParser.CurrentToken.Id == TokenId.Minus || _textParser.CurrentToken.Id == TokenId.Exclamation || To
 26680            {
 26681                Token op = _textParser.CurrentToken;
 26682                _textParser.NextToken();
 23683                 if (op.Id == TokenId.Minus && (_textParser.CurrentToken.Id == TokenId.IntegerLiteral || _textParser.Curr
 23684                {
 23685                    _textParser.CurrentToken.Text = "-" + _textParser.CurrentToken.Text;
 23686                    _textParser.CurrentToken.Pos = op.Pos;
 23687                    return ParsePrimary();
 688                }
 689
 0690                Expression expr = ParseUnary();
 0691                 if (op.Id == TokenId.Minus)
 0692                {
 0693                    CheckAndPromoteOperand(typeof(INegationSignatures), op.Text, ref expr, op.Pos);
 0694                    expr = Expression.Negate(expr);
 0695                }
 696                else
 0697                {
 0698                    CheckAndPromoteOperand(typeof(INotSignatures), op.Text, ref expr, op.Pos);
 0699                    expr = Expression.Not(expr);
 0700                }
 701
 0702                return expr;
 703            }
 704
 1176705            return ParsePrimary();
 1178706        }
 707
 708        Expression ParsePrimary()
 1202709        {
 1202710            Expression expr = ParsePrimaryStart();
 1427711            while (true)
 1427712            {
 1427713                 if (_textParser.CurrentToken.Id == TokenId.Dot)
 244714                {
 244715                    _textParser.NextToken();
 244716                    expr = ParseMemberAccess(null, expr);
 243717                }
 1183718                 else if (_textParser.CurrentToken.Id == TokenId.NullPropagation)
 1719                {
 1720                    throw new NotSupportedException("An expression tree lambda may not contain a null propagating operat
 721                }
 1182722                 else if (_textParser.CurrentToken.Id == TokenId.OpenBracket)
 1723                {
 1724                    expr = ParseElementAccess(expr);
 1725                }
 726                else
 1181727                {
 1181728                    break;
 729                }
 244730            }
 1181731            return expr;
 1181732        }
 733
 734        Expression ParsePrimaryStart()
 1202735        {
 1202736             switch (_textParser.CurrentToken.Id)
 737            {
 738                case TokenId.Identifier:
 899739                    return ParseIdentifier();
 740                case TokenId.StringLiteral:
 38741                    return ParseStringLiteral();
 742                case TokenId.IntegerLiteral:
 203743                    return ParseIntegerLiteral();
 744                case TokenId.RealLiteral:
 19745                    return ParseRealLiteral();
 746                case TokenId.OpenParen:
 41747                    return ParseParenExpression();
 748                default:
 2749                    throw ParseError(Res.ExpressionExpected);
 750            }
 1183751        }
 752
 753        Expression ParseStringLiteral()
 38754        {
 38755            _textParser.ValidateToken(TokenId.StringLiteral);
 38756            char quote = _textParser.CurrentToken.Text[0];
 38757            string s = _textParser.CurrentToken.Text.Substring(1, _textParser.CurrentToken.Text.Length - 2);
 758
 38759             if (quote == '\'')
 0760            {
 0761                 if (s.Length != 1)
 0762                {
 0763                    throw ParseError(Res.InvalidCharacterLiteral);
 764                }
 0765                _textParser.NextToken();
 0766                return ConstantExpressionHelper.CreateLiteral(s[0], s);
 767            }
 38768            _textParser.NextToken();
 38769            return ConstantExpressionHelper.CreateLiteral(s, s);
 38770        }
 771
 772        Expression ParseIntegerLiteral()
 203773        {
 203774            _textParser.ValidateToken(TokenId.IntegerLiteral);
 775
 203776            string text = _textParser.CurrentToken.Text;
 203777            string qualifier = null;
 203778            char last = text[text.Length - 1];
 203779             bool isHexadecimal = text.StartsWith(text[0] == '-' ? "-0x" : "0x", StringComparison.OrdinalIgnoreCase);
 203780            char[] qualifierLetters = isHexadecimal
 203781                                          ? new[] { 'U', 'u', 'L', 'l' }
 203782                                          : new[] { 'U', 'u', 'L', 'l', 'F', 'f', 'D', 'd', 'M', 'm' };
 783
 203784             if (qualifierLetters.Contains(last))
 26785            {
 52786                int pos = text.Length - 1, count = 0;
 56787                 while (qualifierLetters.Contains(text[pos]))
 30788                {
 30789                    ++count;
 30790                    --pos;
 30791                }
 26792                qualifier = text.Substring(text.Length - count, count);
 26793                text = text.Substring(0, text.Length - count);
 26794            }
 795
 203796             if (text[0] != '-')
 188797            {
 188798                 if (isHexadecimal)
 4799                {
 4800                    text = text.Substring(2);
 4801                }
 802
 188803                 if (!ulong.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.Cur
 0804                {
 0805                    throw ParseError(Res.InvalidIntegerLiteral, text);
 806                }
 807
 188808                _textParser.NextToken();
 188809                 if (!string.IsNullOrEmpty(qualifier))
 15810                {
 18811                     if (qualifier == "U" || qualifier == "u") return ConstantExpressionHelper.CreateLiteral((uint)value,
 15812                     if (qualifier == "L" || qualifier == "l") return ConstantExpressionHelper.CreateLiteral((long)value,
 813
 814                    // in case of UL, just return
 9815                    return ConstantExpressionHelper.CreateLiteral(value, text);
 816                }
 817
 818                // if (value <= (int)short.MaxValue) return ConstantExpressionHelper.CreateLiteral((short)value, text);
 346819                 if (value <= int.MaxValue) return ConstantExpressionHelper.CreateLiteral((int)value, text);
 0820                 if (value <= uint.MaxValue) return ConstantExpressionHelper.CreateLiteral((uint)value, text);
 0821                 if (value <= long.MaxValue) return ConstantExpressionHelper.CreateLiteral((long)value, text);
 822
 0823                return ConstantExpressionHelper.CreateLiteral(value, text);
 824            }
 825            else
 15826            {
 15827                 if (isHexadecimal)
 2828                {
 2829                    text = text.Substring(3);
 2830                }
 831
 15832                 if (!long.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.Curr
 0833                {
 0834                    throw ParseError(Res.InvalidIntegerLiteral, text);
 835                }
 836
 15837                 if (isHexadecimal)
 2838                {
 2839                    value = -value;
 2840                }
 841
 15842                _textParser.NextToken();
 15843                 if (!string.IsNullOrEmpty(qualifier))
 11844                {
 11845                     if (qualifier == "L" || qualifier == "l")
 4846                        return ConstantExpressionHelper.CreateLiteral(value, text);
 847
 7848                     if (qualifier == "F" || qualifier == "f")
 2849                        return TryParseAsFloat(text, qualifier[0]);
 850
 5851                     if (qualifier == "D" || qualifier == "d")
 2852                        return TryParseAsDouble(text, qualifier[0]);
 853
 3854                     if (qualifier == "M" || qualifier == "m")
 2855                        return TryParseAsDecimal(text, qualifier[0]);
 856
 1857                    throw ParseError(Res.MinusCannotBeAppliedToUnsignedInteger);
 858                }
 859
 4860                 if (value <= int.MaxValue)
 4861                {
 4862                    return ConstantExpressionHelper.CreateLiteral((int)value, text);
 863                }
 864
 865        Expression ParsePrimary()
 864866        {
 864867            Expression expr = ParsePrimaryStart();
 981868            while (true)
 981869            {
 981870                 if (_textParser.CurrentToken.Id == TokenId.Dot)
 135871                {
 135872                    _textParser.NextToken();
 135873                    expr = ParseMemberAccess(null, expr);
 135874                }
 846875                 else if (_textParser.CurrentToken.Id == TokenId.OpenBracket)
 1876                {
 1877                    expr = ParseElementAccess(expr);
 1878                }
 879                else
 845880                {
 845881                    break;
 882                }
 136883            }
 845884            return expr;
 845885        }
 886
 887        Expression ParsePrimaryStart()
 864888        {
 864889             switch (_textParser.CurrentToken.Id)
 890            {
 891                case TokenId.Identifier:
 662892                    return ParseIdentifier();
 893                case TokenId.StringLiteral:
 28894                    return ParseStringLiteral();
 895                case TokenId.IntegerLiteral:
 154896                    return ParseIntegerLiteral();
 897                case TokenId.RealLiteral:
 11898                    return ParseRealLiteral();
 899                case TokenId.OpenParen:
 9900                    return ParseParenExpression();
 901                default:
 0902                    throw ParseError(Res.ExpressionExpected);
 903            }
 845904        }
 905
 906        Expression ParseStringLiteral()
 28907        {
 28908            _textParser.ValidateToken(TokenId.StringLiteral);
 28909            char quote = _textParser.CurrentToken.Text[0];
 28910            string s = _textParser.CurrentToken.Text.Substring(1, _textParser.CurrentToken.Text.Length - 2);
 911
 28912             if (quote == '\'')
 0913            {
 0914                 if (s.Length != 1)
 0915                    throw ParseError(Res.InvalidCharacterLiteral);
 0916                _textParser.NextToken();
 0917                return CreateLiteral(s[0], s);
 918            }
 28919            _textParser.NextToken();
 28920            return CreateLiteral(s, s);
 28921        }
 922
 923        Expression ParseIntegerLiteral()
 154924        {
 154925            _textParser.ValidateToken(TokenId.IntegerLiteral);
 0865                return ConstantExpressionHelper.CreateLiteral(value, text);
 866            }
 202867        }
 868
 869        Expression ParseRealLiteral()
 19870        {
 19871            _textParser.ValidateToken(TokenId.RealLiteral);
 872
 19873            string text = _textParser.CurrentToken.Text;
 19874            char qualifier = text[text.Length - 1];
 875
 19876            _textParser.NextToken();
 19877            return TryParseAsFloat(text, qualifier);
 19878        }
 879
 880        Expression TryParseAsFloat(string text, char qualifier)
 21881        {
 21882             if (qualifier == 'F' || qualifier == 'f')
 7883            {
 7884                 if (float.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture,
 5885                {
 5886                    return ConstantExpressionHelper.CreateLiteral(f, text);
 887                }
 2888            }
 889
 890            // not possible to find float qualifier, so try to parse as double
 16891            return TryParseAsDecimal(text, qualifier);
 21892        }
 893
 894        Expression TryParseAsDecimal(string text, char qualifier)
 18895        {
 18896             if (qualifier == 'M' || qualifier == 'm')
 7897            {
 7898                 if (decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCultu
 5899                {
 5900                    return ConstantExpressionHelper.CreateLiteral(d, text);
 901                }
 2902            }
 903
 904            // not possible to find float qualifier, so try to parse as double
 13905            return TryParseAsDouble(text, qualifier);
 18906        }
 907
 908        Expression TryParseAsDouble(string text, char qualifier)
 15909        {
 910            double d;
 15911             if (qualifier == 'D' || qualifier == 'd')
 7912            {
 7913                 if (double.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCultur
 5914                {
 5915                    return ConstantExpressionHelper.CreateLiteral(d, text);
 916                }
 2917            }
 918
 10919             if (double.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out d))
 10920            {
 10921                return ConstantExpressionHelper.CreateLiteral(d, text);
 922            }
 923
 0924            throw ParseError(Res.InvalidRealLiteral, text);
 15925        }
 926
 154927            string text = _textParser.CurrentToken.Text;
 154928            string qualifier = null;
 154929            char last = text[text.Length - 1];
 154930             bool isHexadecimal = text.StartsWith(text[0] == '-' ? "-0x" : "0x", StringComparison.CurrentCultureIgnoreCas
 154931            char[] qualifierLetters = isHexadecimal
 154932                                          ? new[] { 'U', 'u', 'L', 'l' }
 154933                                          : new[] { 'U', 'u', 'L', 'l', 'F', 'f', 'D', 'd' };
 934
 154935             if (qualifierLetters.Contains(last))
 22936            {
 44937                int pos = text.Length - 1, count = 0;
 48938                 while (qualifierLetters.Contains(text[pos]))
 26939                {
 26940                    ++count;
 26941                    --pos;
 26942                }
 22943                qualifier = text.Substring(text.Length - count, count);
 22944                text = text.Substring(0, text.Length - count);
 22945            }
 946
 154947             if (text[0] != '-')
 141948            {
 141949                 if (isHexadecimal)
 4950                {
 4951                    text = text.Substring(2);
 4952                }
 953
 954                ulong value;
 141955                 if (!ulong.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.Cur
 0956                    throw ParseError(Res.InvalidIntegerLiteral, text);
 957
 141958                _textParser.NextToken();
 141959                 if (!string.IsNullOrEmpty(qualifier))
 13960                {
 16961                     if (qualifier == "U" || qualifier == "u") return CreateLiteral((uint)value, text);
 13962                     if (qualifier == "L" || qualifier == "l") return CreateLiteral((long)value, text);
 927        Expression ParseParenExpression()
 41928        {
 41929            _textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
 41930            _textParser.NextToken();
 41931            Expression e = ParseConditionalOperator();
 41932            _textParser.ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected);
 41933            _textParser.NextToken();
 41934            return e;
 41935        }
 936
 937        Expression ParseIdentifier()
 899938        {
 899939            _textParser.ValidateToken(TokenId.Identifier);
 940
 899941             if (_keywordsHelper.TryGetValue(_textParser.CurrentToken.Text, out object value))
 408942            {
 408943                var typeValue = value as Type;
 408944                 if (typeValue != null)
 22945                {
 22946                    return ParseTypeAccess(typeValue);
 947                }
 948
 686949                 if (value == (object)KeywordsHelper.KEYWORD_IT) return ParseIt();
 87950                 if (value == (object)KeywordsHelper.KEYWORD_PARENT) return ParseParent();
 85951                 if (value == (object)KeywordsHelper.KEYWORD_ROOT) return ParseRoot();
 87952                 if (value == (object)KeywordsHelper.SYMBOL_IT) return ParseIt();
 84953                 if (value == (object)KeywordsHelper.SYMBOL_PARENT) return ParseParent();
 83954                 if (value == (object)KeywordsHelper.SYMBOL_ROOT) return ParseRoot();
 82955                 if (value == (object)KeywordsHelper.KEYWORD_IIF) return ParseIif();
 141956                 if (value == (object)KeywordsHelper.KEYWORD_NEW) return ParseNew();
 25957                 if (value == (object)KeywordsHelper.KEYWORD_ISNULL) return ParseIsNull();
 958
 13959                _textParser.NextToken();
 960
 13961                return (Expression)value;
 962            }
 963
 964                    // in case of UL, just return
 7965                    return CreateLiteral(value, text);
 966                }
 967
 256968                 if (value <= int.MaxValue) return CreateLiteral((int)value, text);
 0969                 if (value <= uint.MaxValue) return CreateLiteral((uint)value, text);
 0970                 if (value <= long.MaxValue) return CreateLiteral((long)value, text);
 971
 0972                return CreateLiteral(value, text);
 973            }
 974            else
 13975            {
 13976                 if (isHexadecimal)
 2977                {
 2978                    text = text.Substring(3);
 2979                }
 980
 981                long value;
 13982                 if (!long.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.Curr
 0983                    throw ParseError(Res.InvalidIntegerLiteral, text);
 984
 13985                 if (isHexadecimal)
 2986                {
 2987                    value = -value;
 2988                }
 989
 13990                _textParser.NextToken();
 13991                 if (!string.IsNullOrEmpty(qualifier))
 9992                {
 9993                     if (qualifier == "L" || qualifier == "l")
 4994                        return CreateLiteral(value, text);
 995
 5996                     if (qualifier == "F" || qualifier == "f")
 2997                        return TryParseAsFloat(text, qualifier[0]);
 998
 3999                     if (qualifier == "D" || qualifier == "d")
 21000                        return TryParseAsDouble(text, qualifier[0]);
 1001
 11002                    throw ParseError(Res.MinusCannotBeAppliedToUnsignedInteger);
 1003                }
 491964             if (_symbols.TryGetValue(_textParser.CurrentToken.Text, out value) ||
 491965                _externals != null && _externals.TryGetValue(_textParser.CurrentToken.Text, out value) ||
 491966                _internals.TryGetValue(_textParser.CurrentToken.Text, out value))
 195967            {
 195968                Expression expr = value as Expression;
 195969                 if (expr == null)
 140970                {
 140971                    expr = Expression.Constant(value);
 140972                }
 973                else
 55974                {
 55975                    LambdaExpression lambda = expr as LambdaExpression;
 55976                     if (lambda != null)
 0977                    {
 0978                        return ParseLambdaInvocation(lambda);
 979                    }
 55980                }
 981
 195982                _textParser.NextToken();
 983
 195984                return expr;
 985            }
 986
 296987             if (_it != null)
 296988            {
 296989                return ParseMemberAccess(null, _it);
 990            }
 991
 0992            throw ParseError(Res.UnknownIdentifier, _textParser.CurrentToken.Text);
 883993        }
 994
 995        Expression ParseIt()
 302996        {
 302997             if (_it == null)
 0998            {
 0999                throw ParseError(Res.NoItInScope);
 1000            }
 3021001            _textParser.NextToken();
 3021002            return _it;
 3021003        }
 1004
 81005                 if (value <= int.MaxValue) return CreateLiteral((int)value, text);
 1006
 01007                return CreateLiteral(value, text);
 1008            }
 1531009        }
 1010
 1011        Expression ParseRealLiteral()
 111012        {
 111013            _textParser.ValidateToken(TokenId.RealLiteral);
 1005        Expression ParseParent()
 21006        {
 21007             if (_parent == null)
 01008            {
 01009                throw ParseError(Res.NoParentInScope);
 1010            }
 21011            _textParser.NextToken();
 21012            return _parent;
 21013        }
 1014
 111015            string text = _textParser.CurrentToken.Text;
 111016            char qualifier = text[text.Length - 1];
 1017
 111018            _textParser.NextToken();
 111019            return TryParseAsFloat(text, qualifier);
 111020        }
 1021
 1022        Expression TryParseAsFloat(string text, char qualifier)
 131023        {
 131024             if (qualifier == 'F' || qualifier == 'f')
 61025            {
 1026                float f;
 61027                 if (float.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture,
 41028                {
 41029                    return CreateLiteral(f, text);
 1030                }
 21031            }
 1032
 1033            // not possible to find float qualifier, so try to parse as double
 91034            return TryParseAsDouble(text, qualifier);
 131035        }
 1036
 1037        Expression TryParseAsDouble(string text, char qualifier)
 111038        {
 1039            double d;
 111040             if (qualifier == 'D' || qualifier == 'd')
 61041            {
 61042                 if (double.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCultur
 41043                {
 41044                    return CreateLiteral(d, text);
 1045                }
 21046            }
 1047
 71048             if (double.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out d))
 71049            {
 71050                return CreateLiteral(d, text);
 1051            }
 1052
 01053            throw ParseError(Res.InvalidRealLiteral, text);
 111054        }
 1055
 1056        Expression CreateLiteral(object value, string text)
 1921057        {
 1921058            ConstantExpression expr = Expression.Constant(value);
 1921059            _literals.Add(expr, text);
 1921060            return expr;
 1921061        }
 1062
 1063        Expression ParseParenExpression()
 91064        {
 91065            _textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
 91066            _textParser.NextToken();
 91067            Expression e = ParseConditionalOperator();
 91068            _textParser.ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected);
 91069            _textParser.NextToken();
 91070            return e;
 91071        }
 1015        Expression ParseRoot()
 11016        {
 11017             if (_root == null)
 01018            {
 01019                throw ParseError(Res.NoRootInScope);
 1020            }
 11021            _textParser.NextToken();
 11022            return _root;
 11023        }
 1024
 1025        Expression ParseIif()
 11026        {
 11027            int errorPos = _textParser.CurrentToken.Pos;
 11028            _textParser.NextToken();
 11029            Expression[] args = ParseArgumentList();
 11030             if (args.Length != 3)
 01031            {
 01032                throw ParseError(errorPos, Res.IifRequiresThreeArgs);
 1033            }
 1034
 11035            return GenerateConditional(args[0], args[1], args[2], errorPos);
 11036        }
 1037
 1038        Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos)
 21039        {
 21040             if (test.Type != typeof(bool))
 01041            {
 01042                throw ParseError(errorPos, Res.FirstExprMustBeBool);
 1043            }
 1044
 21045             if (expr1.Type != expr2.Type)
 11046            {
 11047                 Expression expr1As2 = expr2 != Constants.NullLiteral ? ExpressionPromoter.Promote(expr1, expr2.Type, tru
 11048                 Expression expr2As1 = expr1 != Constants.NullLiteral ? ExpressionPromoter.Promote(expr2, expr1.Type, tru
 11049                 if (expr1As2 != null && expr2As1 == null)
 01050                {
 01051                    expr1 = expr1As2;
 01052                }
 11053                 else if (expr2As1 != null && expr1As2 == null)
 11054                {
 11055                    expr2 = expr2As1;
 11056                }
 1057                else
 01058                {
 01059                     string type1 = expr1 != Constants.NullLiteral ? expr1.Type.Name : "null";
 01060                     string type2 = expr2 != Constants.NullLiteral ? expr2.Type.Name : "null";
 01061                     if (expr1As2 != null)
 01062                    {
 01063                        throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2);
 1064                    }
 1065
 01066                    throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2);
 1067                }
 11068            }
 1069
 21070            return Expression.Condition(test, expr1, expr2);
 21071        }
 1072
 1073        Expression ParseIdentifier()
 6621074        {
 6621075            _textParser.ValidateToken(TokenId.Identifier);
 1076            object value;
 1077
 6621078             if (_keywords.TryGetValue(_textParser.CurrentToken.Text, out value))
 2981079            {
 2981080                var typeValue = value as Type;
 3141081                 if (typeValue != null) return ParseTypeAccess(typeValue);
 1082
 4901083                 if (value == (object)KEYWORD_IT) return ParseIt();
 751084                 if (value == (object)KEYWORD_PARENT) return ParseParent();
 731085                 if (value == (object)KEYWORD_ROOT) return ParseRoot();
 771086                 if (value == (object)SYMBOL_IT) return ParseIt();
 701087                 if (value == (object)SYMBOL_PARENT) return ParseParent();
 701088                 if (value == (object)SYMBOL_ROOT) return ParseRoot();
 671089                 if (value == (object)KEYWORD_IIF) return ParseIif();
 1141090                 if (value == (object)KEYWORD_NEW) return ParseNew();
 221091                 if (value == (object)KEYWORD_ISNULL) return ParseIsNull();
 1092
 101093                _textParser.NextToken();
 1094
 101095                return (Expression)value;
 1096            }
 1097
 3641098             if (_symbols.TryGetValue(_textParser.CurrentToken.Text, out value) ||
 3641099                _externals != null && _externals.TryGetValue(_textParser.CurrentToken.Text, out value) ||
 3641100                _internals.TryGetValue(_textParser.CurrentToken.Text, out value))
 1111101            {
 1111102                Expression expr = value as Expression;
 1111103                 if (expr == null)
 861104                {
 861105                    expr = Expression.Constant(value);
 861106                }
 1107                else
 251108                {
 251109                    LambdaExpression lambda = expr as LambdaExpression;
 251110                     if (lambda != null) return ParseLambdaInvocation(lambda);
 251111                }
 1112
 1111113                _textParser.NextToken();
 1114
 1111115                return expr;
 1116            }
 1117
 2531118             if (_it != null)
 2531119                return ParseMemberAccess(null, _it);
 1120
 01121            throw ParseError(Res.UnknownIdentifier, _textParser.CurrentToken.Text);
 6441122        }
 1123
 1124        Expression ParseIt()
 2121125        {
 2121126             if (_it == null)
 01127                throw ParseError(Res.NoItInScope);
 2121128            _textParser.NextToken();
 2121129            return _it;
 2121130        }
 1131
 1132        Expression ParseParent()
 21133        {
 21134             if (_parent == null)
 01135                throw ParseError(Res.NoParentInScope);
 21136            _textParser.NextToken();
 21137            return _parent;
 21138        }
 1139
 1140        Expression ParseRoot()
 21141        {
 21142             if (_root == null)
 01143                throw ParseError(Res.NoRootInScope);
 21144            _textParser.NextToken();
 21145            return _root;
 21146        }
 1147
 1148        Expression ParseIif()
 11149        {
 11150            int errorPos = _textParser.CurrentToken.Pos;
 11151            _textParser.NextToken();
 11152            Expression[] args = ParseArgumentList();
 11153             if (args.Length != 3)
 01154                throw ParseError(errorPos, Res.IifRequiresThreeArgs);
 1155
 11156            return GenerateConditional(args[0], args[1], args[2], errorPos);
 11157        }
 1158
 1159        Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos)
 21160        {
 21161             if (test.Type != typeof(bool))
 01162                throw ParseError(errorPos, Res.FirstExprMustBeBool);
 21163             if (expr1.Type != expr2.Type)
 11164            {
 11165                 Expression expr1As2 = expr2 != NullLiteral ? PromoteExpression(expr1, expr2.Type, true, false) : null;
 11166                 Expression expr2As1 = expr1 != NullLiteral ? PromoteExpression(expr2, expr1.Type, true, false) : null;
 11167                 if (expr1As2 != null && expr2As1 == null)
 01168                {
 01169                    expr1 = expr1As2;
 01170                }
 11171                 else if (expr2As1 != null && expr1As2 == null)
 11172                {
 11173                    expr2 = expr2As1;
 11174                }
 1175                else
 01176                {
 01177                     string type1 = expr1 != NullLiteral ? expr1.Type.Name : "null";
 01178                     string type2 = expr2 != NullLiteral ? expr2.Type.Name : "null";
 01179                     if (expr1As2 != null)
 01180                        throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2);
 1181
 01182                    throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2);
 1183                }
 11184            }
 1073        Expression ParseNew()
 611074        {
 611075            _textParser.NextToken();
 611076             if (_textParser.CurrentToken.Id != TokenId.OpenParen &&
 611077                _textParser.CurrentToken.Id != TokenId.OpenCurlyParen &&
 611078                _textParser.CurrentToken.Id != TokenId.OpenBracket &&
 611079                _textParser.CurrentToken.Id != TokenId.Identifier)
 11080            {
 11081                throw ParseError(Res.OpenParenOrIdentifierExpected);
 1082            }
 1083
 601084            Type newType = null;
 601085             if (_textParser.CurrentToken.Id == TokenId.Identifier)
 51086            {
 51087                var newTypeName = _textParser.CurrentToken.Text;
 51088                _textParser.NextToken();
 1089
 111090                 while (_textParser.CurrentToken.Id == TokenId.Dot || _textParser.CurrentToken.Id == TokenId.Plus)
 61091                {
 61092                    var sep = _textParser.CurrentToken.Text;
 61093                    _textParser.NextToken();
 61094                     if (_textParser.CurrentToken.Id != TokenId.Identifier)
 01095                    {
 01096                        throw ParseError(Res.IdentifierExpected);
 1097                    }
 61098                    newTypeName += sep + _textParser.CurrentToken.Text;
 61099                    _textParser.NextToken();
 61100                }
 1101
 51102                newType = FindType(newTypeName);
 51103                 if (newType == null)
 21104                {
 21105                    throw ParseError(_textParser.CurrentToken.Pos, Res.TypeNotFound, newTypeName);
 1106                }
 1107
 31108                 if (_textParser.CurrentToken.Id != TokenId.OpenParen &&
 31109                    _textParser.CurrentToken.Id != TokenId.OpenBracket &&
 31110                    _textParser.CurrentToken.Id != TokenId.OpenCurlyParen)
 01111                {
 01112                    throw ParseError(Res.OpenParenExpected);
 1113                }
 31114            }
 1115
 581116            bool arrayInitializer = false;
 581117             if (_textParser.CurrentToken.Id == TokenId.OpenBracket)
 71118            {
 71119                _textParser.NextToken();
 71120                _textParser.ValidateToken(TokenId.CloseBracket, Res.CloseBracketExpected);
 61121                _textParser.NextToken();
 61122                _textParser.ValidateToken(TokenId.OpenCurlyParen, Res.OpenCurlyParenExpected);
 61123                arrayInitializer = true;
 61124            }
 1125
 571126            _textParser.NextToken();
 1127
 571128            var properties = new List<DynamicProperty>();
 571129            var expressions = new List<Expression>();
 1130
 1261131             while (_textParser.CurrentToken.Id != TokenId.CloseParen && _textParser.CurrentToken.Id != TokenId.CloseCurl
 1251132            {
 1251133                int exprPos = _textParser.CurrentToken.Pos;
 1251134                Expression expr = ParseConditionalOperator();
 1231135                 if (!arrayInitializer)
 1121136                {
 1137                    string propName;
 1121138                     if (TokenIdentifierIs("as"))
 751139                    {
 751140                        _textParser.NextToken();
 751141                        propName = GetIdentifier();
 751142                        _textParser.NextToken();
 751143                    }
 1144                    else
 371145                    {
 371146                         if (!TryGetMemberName(expr, out propName))
 01147                        {
 01148                            throw ParseError(exprPos, Res.MissingAsClause);
 1149                        }
 371150                    }
 1151
 1121152                    properties.Add(new DynamicProperty(propName, expr.Type));
 1121153                }
 1154
 1231155                expressions.Add(expr);
 1156
 1231157                 if (_textParser.CurrentToken.Id != TokenId.Comma)
 541158                {
 541159                    break;
 1160                }
 1161
 691162                _textParser.NextToken();
 691163            }
 1164
 551165             if (_textParser.CurrentToken.Id != TokenId.CloseParen && _textParser.CurrentToken.Id != TokenId.CloseCurlyPa
 21166            {
 21167                throw ParseError(Res.CloseParenOrCommaExpected);
 1168            }
 531169            _textParser.NextToken();
 1170
 531171             if (arrayInitializer)
 61172            {
 61173                return CreateArrayInitializerExpression(expressions, newType);
 1174            }
 1175
 471176            return CreateNewExpression(properties, expressions, newType);
 531177        }
 1178
 1179        private Expression CreateArrayInitializerExpression(List<Expression> expressions, Type newType)
 61180        {
 61181             if (expressions.Count == 0)
 11182            {
 11183                 return Expression.NewArrayInit(newType ?? typeof(object));
 1184            }
 1185
 21186            return Expression.Condition(test, expr1, expr2);
 21187        }
 1188
 1189        Expression ParseNew()
 491190        {
 491191            _textParser.NextToken();
 491192             if (_textParser.CurrentToken.Id != TokenId.OpenParen &&
 491193                _textParser.CurrentToken.Id != TokenId.OpenCurlyParen &&
 491194                _textParser.CurrentToken.Id != TokenId.OpenBracket &&
 491195                _textParser.CurrentToken.Id != TokenId.Identifier)
 11196                throw ParseError(Res.OpenParenOrIdentifierExpected);
 1197
 481198            Type newType = null;
 481199             if (_textParser.CurrentToken.Id == TokenId.Identifier)
 41200            {
 41201                var newTypeName = _textParser.CurrentToken.Text;
 41202                newType = FindType(newTypeName);
 41203                 if (newType == null)
 21204                    throw ParseError(_textParser.CurrentToken.Pos, Res.TypeNotFound, newTypeName);
 21205                _textParser.NextToken();
 21206                 if (_textParser.CurrentToken.Id != TokenId.OpenParen &&
 21207                    _textParser.CurrentToken.Id != TokenId.OpenBracket &&
 21208                    _textParser.CurrentToken.Id != TokenId.OpenCurlyParen)
 01209                    throw ParseError(Res.OpenParenExpected);
 21210            }
 1211
 461212            bool arrayInitializer = false;
 461213             if (_textParser.CurrentToken.Id == TokenId.OpenBracket)
 71214            {
 71215                _textParser.NextToken();
 71216                _textParser.ValidateToken(TokenId.CloseBracket, Res.CloseBracketExpected);
 61217                _textParser.NextToken();
 61218                _textParser.ValidateToken(TokenId.OpenCurlyParen, Res.OpenCurlyParenExpected);
 61219                arrayInitializer = true;
 61220            }
 51186             if (newType != null)
 11187            {
 41188                return Expression.NewArrayInit(newType, expressions.Select(expression => ExpressionPromoter.Promote(expr
 1189            }
 1190
 121191             return Expression.NewArrayInit(expressions.All(expression => expression.Type == expressions[0].Type) ? expre
 61192        }
 1193
 1194        private Expression CreateNewExpression(List<DynamicProperty> properties, List<Expression> expressions, Type newT
 471195        {
 1196            // http://solutionizing.net/category/linq/
 471197             Type type = newType ?? _resultType;
 1198
 471199             if (type == null)
 431200            {
 1201#if !UAP10_0
 431202                 if (_parsingConfig != null && _parsingConfig.UseDynamicObjectClassForAnonymousTypes)
 01203                {
 1204#endif
 01205                    type = typeof(DynamicClass);
 01206                    Type typeForKeyValuePair = typeof(KeyValuePair<string, object>);
 1207#if NET35 || NET40
 1208                    ConstructorInfo constructorForKeyValuePair = typeForKeyValuePair.GetConstructors().First();
 1209#else
 01210                    ConstructorInfo constructorForKeyValuePair = typeForKeyValuePair.GetTypeInfo().DeclaredConstructors.
 1211#endif
 01212                    var arrayIndexParams = new List<Expression>();
 01213                     for (int i = 0; i < expressions.Count; i++)
 01214                    {
 1215                        // Just convert the expression always to an object expression.
 01216                        UnaryExpression boxingExpression = Expression.Convert(expressions[i], typeof(object));
 01217                        NewExpression parameter = Expression.New(constructorForKeyValuePair, (Expression)Expression.Cons
 1218
 01219                        arrayIndexParams.Add(parameter);
 01220                    }
 1221
 451222            _textParser.NextToken();
 1223
 451224            var properties = new List<DynamicProperty>();
 451225            var expressions = new List<Expression>();
 1226
 971227             while (_textParser.CurrentToken.Id != TokenId.CloseParen
 971228                   && _textParser.CurrentToken.Id != TokenId.CloseCurlyParen)
 961229            {
 961230                int exprPos = _textParser.CurrentToken.Pos;
 961231                Expression expr = ParseConditionalOperator();
 941232                 if (!arrayInitializer)
 831233                {
 1234                    string propName;
 831235                     if (TokenIdentifierIs("as"))
 501236                    {
 501237                        _textParser.NextToken();
 501238                        propName = GetIdentifier();
 501239                        _textParser.NextToken();
 501240                    }
 1241                    else
 331242                    {
 331243                         if (!TryGetMemberName(expr, out propName)) throw ParseError(exprPos, Res.MissingAsClause);
 331244                    }
 1245
 831246                    properties.Add(new DynamicProperty(propName, expr.Type));
 831247                }
 1248
 941249                expressions.Add(expr);
 1222                    // Create an expression tree that represents creating and initializing a one-dimensional array of ty
 01223                    NewArrayExpression newArrayExpression = Expression.NewArrayInit(typeof(KeyValuePair<string, object>)
 1224
 1225                    // Get the "public DynamicClass(KeyValuePair<string, object>[] propertylist)" constructor
 1226#if NET35 || NET40
 1227                    ConstructorInfo constructor = type.GetConstructors().First();
 1228#else
 01229                    ConstructorInfo constructor = type.GetTypeInfo().DeclaredConstructors.First();
 1230#endif
 01231                    return Expression.New(constructor, newArrayExpression);
 1232#if !UAP10_0
 1233                }
 1234
 431235                type = DynamicClassFactory.CreateType(properties, _createParameterCtor);
 1236#endif
 431237            }
 1238
 471239            IEnumerable<PropertyInfo> propertyInfos = type.GetProperties();
 471240             if (type.GetTypeInfo().BaseType == typeof(DynamicClass))
 431241            {
 2891242                propertyInfos = propertyInfos.Where(x => x.Name != "Item");
 431243            }
 1244
 1571245            Type[] propertyTypes = propertyInfos.Select(p => p.PropertyType).ToArray();
 471246            ConstructorInfo ctor = type.GetConstructor(propertyTypes);
 471247             if (ctor != null && ctor.GetParameters().Length == expressions.Count)
 371248            {
 371249                var expressionsPromoted = new List<Expression>();
 1250
 941251                 if (_textParser.CurrentToken.Id != TokenId.Comma)
 421252                    break;
 1253
 521254                _textParser.NextToken();
 521255            }
 1251                // Loop all expressions and promote if needed
 2361252                 for (int i = 0; i < propertyTypes.Length; i++)
 811253                {
 811254                    Type propertyType = propertyTypes[i];
 811255                    Type expressionType = expressions[i].Type;
 1256
 431257             if (_textParser.CurrentToken.Id != TokenId.CloseParen &&
 431258                _textParser.CurrentToken.Id != TokenId.CloseCurlyParen)
 21259                throw ParseError(Res.CloseParenOrCommaExpected);
 411260            _textParser.NextToken();
 1261
 411262             if (arrayInitializer)
 61263            {
 61264                return CreateArrayInitializerExpression(expressions, newType);
 1265            }
 1266
 351267            return CreateNewExpression(properties, expressions, newType);
 411268        }
 1269
 1270        private Expression CreateArrayInitializerExpression(List<Expression> expressions, Type newType)
 61271        {
 61272             if (expressions.Count == 0)
 11273            {
 11274                 return Expression.NewArrayInit(newType ?? typeof(object));
 1275            }
 1276
 51277             if (newType != null)
 11278            {
 11279                return Expression.NewArrayInit(
 11280                    newType,
 41281                    expressions.Select(expression => PromoteExpression(expression, newType, true, true)));
 1282            }
 1283
 41284             return Expression.NewArrayInit(
 121285                expressions.All(expression => expression.Type == expressions[0].Type) ? expressions[0].Type : typeof(obj
 41286                expressions);
 61287        }
 1288
 1289        private Expression CreateNewExpression(List<DynamicProperty> properties, List<Expression> expressions, Type newT
 351290        {
 1291            // http://solutionizing.net/category/linq/
 351292             Type type = newType ?? _resultType;
 1293
 351294             if (type == null)
 341295            {
 1296#if UAP10_0
 1297                type = typeof(DynamicClass);
 1298                Type typeForKeyValuePair = typeof(KeyValuePair<string, object>);
 1299                ConstructorInfo constructorForKeyValuePair = typeForKeyValuePair.GetTypeInfo().DeclaredConstructors.Firs
 1300
 1301                var arrayIndexParams = new List<Expression>();
 1302                for (int i = 0; i < expressions.Count; i++)
 1303                {
 1304                    // Just convert the expression always to an object expression.
 1305                    UnaryExpression boxingExpression = Expression.Convert(expressions[i], typeof(object));
 1306                    NewExpression parameter = Expression.New(constructorForKeyValuePair, new[] { (Expression)Expression.
 1307
 1308                    arrayIndexParams.Add(parameter);
 1309                }
 1310
 1311                // Create an expression tree that represents creating and initializing a one-dimensional array of type K
 1312                NewArrayExpression newArrayExpression = Expression.NewArrayInit(typeof(KeyValuePair<string, object>), ar
 1313
 1314                // Get the "public DynamicClass(KeyValuePair<string, object>[] propertylist)" constructor
 1315                ConstructorInfo constructor = type.GetTypeInfo().DeclaredConstructors.First();
 1316                return Expression.New(constructor, newArrayExpression);
 1317#else
 341318                type = DynamicClassFactory.CreateType(properties, _createParameterCtor);
 1319#endif
 341320            }
 1321
 1491322            Type[] propertyTypes = type.GetProperties().Select(p => p.PropertyType).ToArray();
 351323            ConstructorInfo ctor = type.GetConstructor(propertyTypes);
 351324             if (ctor != null)
 01325                return Expression.New(ctor, expressions);
 1326
 351327            MemberBinding[] bindings = new MemberBinding[properties.Count];
 2201328             for (int i = 0; i < bindings.Length; i++)
 751329                bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
 351330            return Expression.MemberInit(Expression.New(type), bindings);
 351331        }
 1332
 1333        Expression ParseLambdaInvocation(LambdaExpression lambda)
 01334        {
 01335            int errorPos = _textParser.CurrentToken.Pos;
 01336            _textParser.NextToken();
 01337            Expression[] args = ParseArgumentList();
 1338            MethodBase method;
 01339             if (FindMethod(lambda.Type, "Invoke", false, args, out method) != 1)
 01340                throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda);
 1257                    // Promote from Type to Nullable Type if needed
 811258                    expressionsPromoted.Add(ExpressionPromoter.Promote(expressions[i], propertyType, true, true));
 811259                }
 1260
 371261                return Expression.New(ctor, expressionsPromoted, (IEnumerable<MemberInfo>)propertyInfos);
 1262            }
 1263
 101264            MemberBinding[] bindings = new MemberBinding[properties.Count];
 661265             for (int i = 0; i < bindings.Length; i++)
 231266            {
 231267                PropertyInfo property = type.GetProperty(properties[i].Name);
 231268                Type propertyType = property.PropertyType;
 231269                Type expressionType = expressions[i].Type;
 1270
 1271                // Promote from Type to Nullable Type if needed
 231272                bindings[i] = Expression.Bind(property, ExpressionPromoter.Promote(expressions[i], propertyType, true, t
 231273            }
 1274
 101275            return Expression.MemberInit(Expression.New(type), bindings);
 471276        }
 1277
 1278        Expression ParseLambdaInvocation(LambdaExpression lambda)
 01279        {
 01280            int errorPos = _textParser.CurrentToken.Pos;
 01281            _textParser.NextToken();
 01282            Expression[] args = ParseArgumentList();
 01283             if (MethodFinder.FindMethod(lambda.Type, nameof(Expression.Invoke), false, args, out MethodBase _) != 1)
 01284            {
 01285                throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda);
 1286            }
 1287
 01288            return Expression.Invoke(lambda, args);
 01289        }
 1290
 1291        Expression ParseTypeAccess(Type type)
 221292        {
 221293            int errorPos = _textParser.CurrentToken.Pos;
 221294            _textParser.NextToken();
 1295
 221296             if (_textParser.CurrentToken.Id == TokenId.Question)
 71297            {
 71298                 if (!type.GetTypeInfo().IsValueType || TypeHelper.IsNullableType(type))
 01299                {
 01300                    throw ParseError(errorPos, Res.TypeHasNoNullableForm, TypeHelper.GetTypeName(type));
 1301                }
 1302
 71303                type = typeof(Nullable<>).MakeGenericType(type);
 71304                _textParser.NextToken();
 71305            }
 1306
 1307            // This is a shorthand for explicitely converting a string to something
 221308            bool shorthand = _textParser.CurrentToken.Id == TokenId.StringLiteral;
 221309             if (_textParser.CurrentToken.Id == TokenId.OpenParen || shorthand)
 141310            {
 141311                 Expression[] args = shorthand ? new[] { ParseStringLiteral() } : ParseArgumentList();
 1312
 1313                // If only 1 argument, and if the type is a ValueType and argType is also a ValueType, just Convert
 141314                 if (args.Length == 1)
 141315                {
 141316                    Type argType = args[0].Type;
 1317
 141318                     if (type.GetTypeInfo().IsValueType && TypeHelper.IsNullableType(type) && argType.GetTypeInfo().IsVal
 71319                    {
 71320                        return Expression.Convert(args[0], type);
 1321                    }
 71322                }
 1323
 71324                 switch (MethodFinder.FindBestMethod(type.GetConstructors(), args, out MethodBase method))
 1325                {
 1326                    case 0:
 61327                         if (args.Length == 1)
 61328                        {
 61329                            return GenerateConversion(args[0], type, errorPos);
 1330                        }
 1331
 01332                        throw ParseError(errorPos, Res.NoMatchingConstructor, TypeHelper.GetTypeName(type));
 1333
 1334                    case 1:
 11335                        return Expression.New((ConstructorInfo)method, args);
 1336
 1337                    default:
 01338                        throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, TypeHelper.GetTypeName(type));
 1339                }
 1340            }
 1341
 01342            return Expression.Invoke(lambda, args);
 01343        }
 81342            _textParser.ValidateToken(TokenId.Dot, Res.DotOrOpenParenOrStringLiteralExpected);
 81343            _textParser.NextToken();
 1344
 1345        Expression ParseTypeAccess(Type type)
 161346        {
 161347            int errorPos = _textParser.CurrentToken.Pos;
 161348            _textParser.NextToken();
 1349
 161350             if (_textParser.CurrentToken.Id == TokenId.Question)
 51351            {
 51352                 if (!type.GetTypeInfo().IsValueType || IsNullableType(type))
 01353                    throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type));
 1354
 51355                type = typeof(Nullable<>).MakeGenericType(type);
 51356                _textParser.NextToken();
 51357            }
 1358
 1359            // This is a shorthand for explicitely converting a string to something
 161360            bool shorthand = _textParser.CurrentToken.Id == TokenId.StringLiteral;
 161361             if (_textParser.CurrentToken.Id == TokenId.OpenParen || shorthand)
 121362            {
 121363                 Expression[] args = shorthand ? new[] { ParseStringLiteral() } : ParseArgumentList();
 1364
 1365                // If only 1 argument, and if the type is a ValueType and argType is also a ValueType, just Convert
 121366                 if (args.Length == 1)
 121367                {
 121368                    Type argType = args[0].Type;
 1369
 121370                     if (type.GetTypeInfo().IsValueType && IsNullableType(type) && argType.GetTypeInfo().IsValueType)
 51371                    {
 51372                        return Expression.Convert(args[0], type);
 1373                    }
 71374                }
 1375
 1376                MethodBase method;
 71377                 switch (FindBestMethod(type.GetConstructors(), args, out method))
 1378                {
 1379                    case 0:
 61380                         if (args.Length == 1)
 61381                            return GenerateConversion(args[0], type, errorPos);
 1382
 01383                        throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type));
 81345            return ParseMemberAccess(type, null);
 221346        }
 1347
 1348        static Expression GenerateConversion(Expression expr, Type type, int errorPos)
 61349        {
 61350            Type exprType = expr.Type;
 61351             if (exprType == type)
 01352            {
 01353                return expr;
 1354            }
 1355
 61356             if (exprType.GetTypeInfo().IsValueType && type.GetTypeInfo().IsValueType)
 51357            {
 51358                 if ((TypeHelper.IsNullableType(exprType) || TypeHelper.IsNullableType(type)) && TypeHelper.GetNonNullabl
 01359                {
 01360                    return Expression.Convert(expr, type);
 1361                }
 1362
 51363                 if ((TypeHelper.IsNumericType(exprType) || TypeHelper.IsEnumType(exprType)) && TypeHelper.IsNumericType(
 51364                {
 51365                    return Expression.ConvertChecked(expr, type);
 1366                }
 01367            }
 1368
 11369             if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) || exprType.GetTypeInfo().IsInterface
 11370            {
 11371                return Expression.Convert(expr, type);
 1372            }
 1373
 1374            // Try to Parse the string rather that just generate the convert statement
 01375             if (expr.NodeType == ExpressionType.Constant && exprType == typeof(string))
 01376            {
 01377                string text = (string)((ConstantExpression)expr).Value;
 1378
 1379                // DateTime is parsed as UTC time.
 01380                 if (type == typeof(DateTime) && DateTime.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.Non
 01381                {
 01382                    return Expression.Constant(dateTime, type);
 1383                }
 1384
 1385                    case 1:
 11386                        return Expression.New((ConstructorInfo)method, args);
 1387
 1388                    default:
 01389                        throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type));
 1390                }
 1391            }
 1392
 41393            _textParser.ValidateToken(TokenId.Dot, Res.DotOrOpenParenOrStringLiteralExpected);
 41394            _textParser.NextToken();
 1395
 41396            return ParseMemberAccess(type, null);
 161397        }
 1398
 1399        static Expression GenerateConversion(Expression expr, Type type, int errorPos)
 61400        {
 61401            Type exprType = expr.Type;
 61402             if (exprType == type)
 01403                return expr;
 1404
 61405             if (exprType.GetTypeInfo().IsValueType && type.GetTypeInfo().IsValueType)
 51406            {
 51407                 if ((IsNullableType(exprType) || IsNullableType(type)) && GetNonNullableType(exprType) == GetNonNullable
 01408                    return Expression.Convert(expr, type);
 1409
 51410                 if ((IsNumericType(exprType) || IsEnumType(exprType)) && IsNumericType(type) || IsEnumType(type))
 51411                    return Expression.ConvertChecked(expr, type);
 01412            }
 1413
 11414             if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) || exprType.GetTypeInfo().IsInterface
 11415                return Expression.Convert(expr, type);
 1416
 1417            // Try to Parse the string rather that just generate the convert statement
 01418             if (expr.NodeType == ExpressionType.Constant && exprType == typeof(string))
 01419            {
 01420                string text = (string)((ConstantExpression)expr).Value;
 1421
 1422                // DateTime is parsed as UTC time.
 1423                DateTime dateTime;
 01424                 if (type == typeof(DateTime) && DateTime.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.Non
 01425                    return Expression.Constant(dateTime, type);
 1426
 01427                object[] arguments = { text, null };
 1428#if NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD
 01429                MethodInfo method = type.GetMethod("TryParse", new[] { typeof(string), type.MakeByRefType() });
 1430#else
 1431                MethodInfo method = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, null, new Type
 1432#endif
 01433                 if (method != null && (bool)method.Invoke(null, arguments))
 01434                    return Expression.Constant(arguments[1], type);
 01435            }
 1436
 01437            throw ParseError(errorPos, Res.CannotConvertValue, GetTypeName(exprType), GetTypeName(type));
 61438        }
 1439
 1440        Expression ParseMemberAccess(Type type, Expression instance)
 3921441        {
 7801442             if (instance != null) type = instance.Type;
 3921443            int errorPos = _textParser.CurrentToken.Pos;
 3921444            string id = GetIdentifier();
 3921445            _textParser.NextToken();
 1446
 3921447             if (_textParser.CurrentToken.Id == TokenId.OpenParen)
 671448            {
 671449                 if (instance != null && type != typeof(string))
 631450                {
 631451                    Type enumerableType = FindGenericType(typeof(IEnumerable<>), type);
 631452                     if (enumerableType != null)
 531453                    {
 531454                        Type elementType = enumerableType.GetTypeInfo().GetGenericTypeArguments()[0];
 531455                        return ParseAggregate(instance, elementType, id, errorPos);
 1456                    }
 101457                }
 1458
 141459                Expression[] args = ParseArgumentList();
 1460                MethodBase mb;
 141461                 switch (FindMethod(type, id, instance == null, args, out mb))
 1462                {
 1463                    case 0:
 01464                        throw ParseError(errorPos, Res.NoApplicableMethod, id, GetTypeName(type));
 1465
 1466                    case 1:
 141467                        MethodInfo method = (MethodInfo)mb;
 141468                         if (!IsPredefinedType(method.DeclaringType) && !(method.IsPublic && IsPredefinedType(method.Retu
 01469                            throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType));
 1470
 141471                         if (method.ReturnType == typeof(void))
 01472                            throw ParseError(errorPos, Res.MethodIsVoid, id, GetTypeName(method.DeclaringType));
 1473
 141474                        return Expression.Call(instance, method, args);
 1475
 1476                    default:
 01477                        throw ParseError(errorPos, Res.AmbiguousMethodInvocation, id, GetTypeName(type));
 1478                }
 1479            }
 1480
 3251481             if (type.GetTypeInfo().IsEnum)
 61482            {
 61483                var @enum = Enum.Parse(type, id, true);
 01385                object[] arguments = { text, null };
 1386#if NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD
 01387                MethodInfo method = type.GetMethod("TryParse", new[] { typeof(string), type.MakeByRefType() });
 1388#else
 1389                MethodInfo method = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, null, new Type
 1390#endif
 01391                 if (method != null && (bool)method.Invoke(null, arguments))
 01392                {
 01393                    return Expression.Constant(arguments[1], type);
 1394                }
 01395            }
 1396
 01397            throw ParseError(errorPos, Res.CannotConvertValue, TypeHelper.GetTypeName(exprType), TypeHelper.GetTypeName(
 61398        }
 1399
 1400        Expression ParseMemberAccess(Type type, Expression instance)
 5481401        {
 5481402             if (instance != null)
 5401403            {
 5401404                type = instance.Type;
 5401405            }
 1406
 5481407            int errorPos = _textParser.CurrentToken.Pos;
 5481408            string id = GetIdentifier();
 5481409            _textParser.NextToken();
 1410
 5481411             if (_textParser.CurrentToken.Id == TokenId.OpenParen)
 981412            {
 981413                 if (instance != null && type != typeof(string))
 941414                {
 941415                    Type enumerableType = TypeHelper.FindGenericType(typeof(IEnumerable<>), type);
 941416                     if (enumerableType != null)
 831417                    {
 831418                        Type elementType = enumerableType.GetTypeInfo().GetGenericTypeArguments()[0];
 831419                        return ParseAggregate(instance, elementType, id, errorPos, TypeHelper.FindGenericType(typeof(IQu
 1420                    }
 111421                }
 1422
 151423                Expression[] args = ParseArgumentList();
 151424                 switch (MethodFinder.FindMethod(type, id, instance == null, args, out MethodBase mb))
 1425                {
 1426                    case 0:
 01427                        throw ParseError(errorPos, Res.NoApplicableMethod, id, TypeHelper.GetTypeName(type));
 1428
 1429                    case 1:
 151430                        MethodInfo method = (MethodInfo)mb;
 151431                         if (!PredefinedTypesHelper.IsPredefinedType(_parsingConfig, method.DeclaringType) && !(method.Is
 11432                        {
 11433                            throw ParseError(errorPos, Res.MethodsAreInaccessible, TypeHelper.GetTypeName(method.Declari
 1434                        }
 1435
 141436                         if (method.ReturnType == typeof(void))
 01437                        {
 01438                            throw ParseError(errorPos, Res.MethodIsVoid, id, TypeHelper.GetTypeName(method.DeclaringType
 1439                        }
 1440
 141441                        return Expression.Call(instance, method, args);
 1442
 1443                    default:
 01444                        throw ParseError(errorPos, Res.AmbiguousMethodInvocation, id, TypeHelper.GetTypeName(type));
 1445                }
 1446            }
 1447
 4501448             if (type.GetTypeInfo().IsEnum)
 111449            {
 111450                var @enum = Enum.Parse(type, id, true);
 1451
 111452                return Expression.Constant(@enum);
 1453            }
 1454
 1455#if UAP10_0 || NETSTANDARD1_3
 4391456             if (type == typeof(DynamicClass))
 01457            {
 01458                return Expression.MakeIndex(instance, typeof(DynamicClass).GetProperty("Item"), new[] { Expression.Const
 1459            }
 1460#endif
 4391461            MemberInfo member = FindPropertyOrField(type, id, instance == null);
 4391462             if (member is PropertyInfo property)
 4131463            {
 4131464                return Expression.Property(instance, property);
 1465            }
 1466
 261467             if (member is FieldInfo field)
 01468            {
 01469                return Expression.Field(instance, field);
 1470            }
 1471
 1472#if !NET35 && !UAP10_0 && !NETSTANDARD1_3
 1473            if (type == typeof(object))
 1474            {
 1475                return Expression.Dynamic(new DynamicGetMemberBinder(id), type, instance);
 1476            }
 1477#endif
 1478
 261479            MethodInfo indexerMethod = instance.Type.GetMethod("get_Item", new[] { typeof(string) });
 261480             if (indexerMethod != null)
 01481            {
 01482                return Expression.Call(instance, indexerMethod, Expression.Constant(id));
 1483            }
 1484
 61485                return Expression.Constant(@enum);
 1486            }
 1487
 1488#if NETFX_CORE
 1489            if (type == typeof(DynamicObjectClass))
 1490            {
 1491                return Expression.MakeIndex(instance, typeof(DynamicObjectClass).GetProperty("Item"), new[] { Expression
 261485             if (_textParser.CurrentToken.Id == TokenId.Lambda && _it.Type == type)
 191486            {
 1487                // This might be an internal variable for use within a lambda expression, so store it as such
 191488                _internals.Add(id, _it);
 191489                _textParser.NextToken();
 1490
 191491                return ParseConditionalOperator();
 1492            }
 1493#endif
 3191494            MemberInfo member = FindPropertyOrField(type, id, instance == null);
 3191495             if (member == null)
 151496            {
 151497                 if (_textParser.CurrentToken.Id == TokenId.Lambda && _it.Type == type)
 61498                {
 1499                    // This might be an internal variable for use within a lambda expression, so store it as such
 61500                    _internals.Add(id, _it);
 61501                    _textParser.NextToken();
 1502
 61503                    return ParseConditionalOperator();
 1504                }
 1505                else
 91506                {
 91507                    throw ParseError(errorPos, Res.UnknownPropertyOrField, id, GetTypeName(type));
 1508                }
 1509
 1510            }
 1511
 3041512            var property = member as PropertyInfo;
 3041513             if (property != null)
 3041514                return Expression.Property(instance, property);
 1515
 01516            return Expression.Field(instance, (FieldInfo)member);
 3831517        }
 1518
 1519        static Type FindGenericType(Type generic, Type type)
 2021520        {
 2361521             while (type != null && type != typeof(object))
 2021522            {
 2021523                 if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == generic)
 531524                    return type;
 1491525                 if (generic.GetTypeInfo().IsInterface)
 1491526                {
 6101527                    foreach (Type intfType in type.GetInterfaces())
 1391528                    {
 1391529                        Type found = FindGenericType(generic, intfType);
 2541530                         if (found != null) return found;
 241531                    }
 341532                }
 341533                type = type.GetTypeInfo().BaseType;
 341534            }
 341535            return null;
 2021536        }
 1493
 71494            throw ParseError(errorPos, Res.UnknownPropertyOrField, id, TypeHelper.GetTypeName(type));
 5401495        }
 1496
 1497        Type FindType(string name)
 51498        {
 51499            _keywordsHelper.TryGetValue(name, out object type);
 1500
 51501            var result = type as Type;
 51502             if (result != null)
 21503            {
 21504                return result;
 1505            }
 31506             if (_it != null && _it.Type.Name == name)
 11507            {
 11508                return _it.Type;
 1509            }
 21510             if (_parent != null && _parent.Type.Name == name)
 01511            {
 01512                return _parent.Type;
 1513            }
 21514             if (_root != null && _root.Type.Name == name)
 01515            {
 01516                return _root.Type;
 1517            }
 21518             if (_it != null && _it.Type.Namespace + "." + _it.Type.Name == name)
 01519            {
 01520                return _it.Type;
 1521            }
 21522             if (_parent != null && _parent.Type.Namespace + "." + _parent.Type.Name == name)
 01523            {
 01524                return _parent.Type;
 1525            }
 21526             if (_root != null && _root.Type.Namespace + "." + _root.Type.Name == name)
 01527            {
 01528                return _root.Type;
 1529            }
 1530
 21531            return null;
 51532        }
 1533
 1534        Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos, bool isQueryab
 831535        {
 831536            var oldParent = _parent;
 1537
 1538        Type FindType(string name)
 41539        {
 1540            object type;
 41541            _keywords.TryGetValue(name, out type);
 41542            var result = type as Type;
 41543             if (result != null)
 11544                return result;
 31545             if (_it != null && _it.Type.Name == name)
 11546                return _it.Type;
 21547             if (_parent != null && _parent.Type.Name == name)
 01548                return _parent.Type;
 21549             if (_root != null && _root.Type.Name == name)
 01550                return _root.Type;
 21551             if (_it != null && _it.Type.Namespace + "." + _it.Type.Name == name)
 01552                return _it.Type;
 21553             if (_parent != null && _parent.Type.Namespace + "." + _parent.Type.Name == name)
 01554                return _parent.Type;
 21555             if (_root != null && _root.Type.Namespace + "." + _root.Type.Name == name)
 01556                return _root.Type;
 21557            return null;
 41558        }
 1559
 1560        Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
 531561        {
 531562            var oldParent = _parent;
 1563
 531564            ParameterExpression outerIt = _it;
 531565            ParameterExpression innerIt = Expression.Parameter(elementType, "");
 1566
 531567            _parent = _it;
 831538            ParameterExpression outerIt = _it;
 831539            ParameterExpression innerIt = ParameterExpressionHelper.CreateParameterExpression(elementType, string.Empty)
 1540
 831541            _parent = _it;
 1542
 831543             if (methodName == "Contains" || methodName == "Skip" || methodName == "Take")
 71544            {
 1545                // for any method that acts on the parent element type, we need to specify the outerIt as scope.
 71546                _it = outerIt;
 71547            }
 1548            else
 761549            {
 761550                _it = innerIt;
 761551            }
 1552
 831553            Expression[] args = ParseArgumentList();
 1554
 831555            _it = outerIt;
 831556            _parent = oldParent;
 1557
 831558             if (!MethodFinder.ContainsMethod(typeof(IEnumerableSignatures), methodName, false, args))
 01559            {
 01560                throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);
 1561            }
 1562
 831563            Type callType = typeof(Enumerable);
 831564             if (isQueryable && MethodFinder.ContainsMethod(typeof(IQueryableSignatures), methodName, false, args))
 151565            {
 151566                callType = typeof(Queryable);
 151567            }
 1568
 531569             if (methodName == "Contains" || methodName == "Skip" || methodName == "Take")
 61570            {
 1571                //for any method that acts on the parent element type, we need to specify the outerIt as scope.
 61572                _it = outerIt;
 61573            }
 1574            else
 471575            {
 471576                _it = innerIt;
 471577            }
 1578
 531579            Expression[] args = ParseArgumentList();
 1580
 531581            _it = outerIt;
 531582            _parent = oldParent;
 1583
 1584            MethodBase signature;
 531585             if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1)
 01586                throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);
 1587
 1588            Type[] typeArgs;
 531589             if (new[] { "Min", "Max", "Select", "OrderBy", "OrderByDescending", "ThenBy", "ThenByDescending", "GroupBy" 
 141590            {
 141591                typeArgs = new[] { elementType, args[0].Type };
 141592            }
 391593             else if (signature.Name == "SelectMany")
 31594            {
 31595                var type = Expression.Lambda(args[0], innerIt).Body.Type;
 31596                var interfaces = type.GetInterfaces().Union(new[] { type });
 301597                Type interfaceType = interfaces.Single(i => i.Name == typeof(IEnumerable<>).Name);
 31598                Type resultType = interfaceType.GetTypeInfo().GetGenericTypeArguments()[0];
 31599                typeArgs = new[] { elementType, resultType };
 31600            }
 1601            else
 361602            {
 361603                typeArgs = new[] { elementType };
 361604            }
 1605
 531606             if (signature.Name == "Contains" || signature.Name == "Take" || signature.Name == "Skip")
 61607            {
 61608                args = new[] { instance, args[0] };
 61609            }
 471610             else if (args.Length == 0)
 121611            {
 121612                args = new[] { instance };
 121613            }
 1614            else
 351615            {
 351616                args = new[] { instance, Expression.Lambda(args[0], innerIt) };
 351617            }
 1618
 531619            return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args);
 531620        }
 1621
 1622        Expression[] ParseArgumentList()
 861623        {
 861624            _textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
 861625            _textParser.NextToken();
 861626             Expression[] args = _textParser.CurrentToken.Id != TokenId.CloseParen ? ParseArguments() : new Expression[0]
 861627            _textParser.ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
 861628            _textParser.NextToken();
 861629            return args;
 861630        }
 1631
 1632        Expression[] ParseArguments()
 721633        {
 721634            List<Expression> argList = new List<Expression>();
 811635            while (true)
 811636            {
 811637                argList.Add(ParseConditionalOperator());
 1638
 811639                 if (_textParser.CurrentToken.Id != TokenId.Comma)
 721640                    break;
 1569            Type[] typeArgs;
 831570             if (new[] { "Min", "Max", "Select", "OrderBy", "OrderByDescending", "ThenBy", "ThenByDescending", "GroupBy" 
 211571            {
 211572                 if (args.Length == 2)
 11573                {
 11574                    typeArgs = new[] { elementType, args[0].Type, args[1].Type };
 11575                }
 1576                else
 201577                {
 201578                    typeArgs = new[] { elementType, args[0].Type };
 201579                }
 211580            }
 621581             else if (methodName == "SelectMany")
 31582            {
 31583                var type = Expression.Lambda(args[0], innerIt).Body.Type;
 31584                var interfaces = type.GetInterfaces().Union(new[] { type });
 301585                Type interfaceType = interfaces.Single(i => i.Name == typeof(IEnumerable<>).Name);
 31586                Type resultType = interfaceType.GetTypeInfo().GetGenericTypeArguments()[0];
 31587                typeArgs = new[] { elementType, resultType };
 31588            }
 1589            else
 591590            {
 591591                typeArgs = new[] { elementType };
 591592            }
 1593
 831594             if (args.Length == 0)
 261595            {
 261596                args = new[] { instance };
 261597            }
 1598            else
 571599            {
 571600                 if (new[] { "Contains", "Take", "Skip", "DefaultIfEmpty" }.Contains(methodName))
 91601                {
 91602                    args = new[] { instance, args[0] };
 91603                }
 1604                else
 481605                {
 481606                     if (args.Length == 2)
 11607                    {
 11608                        args = new[] { instance, Expression.Lambda(args[0], innerIt), Expression.Lambda(args[1], innerIt
 11609                    }
 1610                    else
 471611                    {
 471612                        args = new[] { instance, Expression.Lambda(args[0], innerIt) };
 471613                    }
 481614                }
 571615            }
 1616
 831617            return Expression.Call(callType, methodName, typeArgs, args);
 831618        }
 1619
 1620        Expression[] ParseArgumentList()
 1191621        {
 1191622            _textParser.ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
 1191623            _textParser.NextToken();
 1191624             Expression[] args = _textParser.CurrentToken.Id != TokenId.CloseParen ? ParseArguments() : new Expression[0]
 1191625            _textParser.ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
 1191626            _textParser.NextToken();
 1191627            return args;
 1191628        }
 1629
 1630        Expression[] ParseArguments()
 901631        {
 901632            var argList = new List<Expression>();
 1001633            while (true)
 1001634            {
 1001635                argList.Add(ParseConditionalOperator());
 1636
 1001637                 if (_textParser.CurrentToken.Id != TokenId.Comma)
 901638                {
 901639                    break;
 1640                }
 1641
 91642                _textParser.NextToken();
 91643            }
 101642                _textParser.NextToken();
 101643            }
 1644
 721645            return argList.ToArray();
 721646        }
 901645            return argList.ToArray();
 901646        }
 1647
 1648        Expression ParseElementAccess(Expression expr)
 11649        {
 11650            int errorPos = _textParser.CurrentToken.Pos;
 11651            _textParser.ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected);
 11652            _textParser.NextToken();
 11653            Expression[] args = ParseArguments();
 11654            _textParser.ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected);
 11655            _textParser.NextToken();
 11656             if (expr.Type.IsArray)
 01657            {
 01658                 if (expr.Type.GetArrayRank() != 1 || args.Length != 1)
 01659                    throw ParseError(errorPos, Res.CannotIndexMultiDimArray);
 01660                Expression index = PromoteExpression(args[0], typeof(int), true, false);
 01661                 if (index == null)
 01662                    throw ParseError(errorPos, Res.InvalidIndex);
 01663                return Expression.ArrayIndex(expr, index);
 1664            }
 1665            else
 11666            {
 1667                MethodBase mb;
 11668                 switch (FindIndexer(expr.Type, args, out mb))
 1669                {
 1670                    case 0:
 01671                        throw ParseError(errorPos, Res.NoApplicableIndexer,
 01672                            GetTypeName(expr.Type));
 1673                    case 1:
 11674                        return Expression.Call(expr, (MethodInfo)mb, args);
 1675                    default:
 01676                        throw ParseError(errorPos, Res.AmbiguousIndexerInvocation,
 01677                            GetTypeName(expr.Type));
 1678                }
 1679            }
 11680        }
 1653
 11654            Expression[] args = ParseArguments();
 11655            _textParser.ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected);
 11656            _textParser.NextToken();
 1657
 11658             if (expr.Type.IsArray)
 01659            {
 01660                 if (expr.Type.GetArrayRank() != 1 || args.Length != 1)
 01661                {
 01662                    throw ParseError(errorPos, Res.CannotIndexMultiDimArray);
 1663                }
 01664                Expression index = ExpressionPromoter.Promote(args[0], typeof(int), true, false);
 1665
 01666                 if (index == null)
 01667                {
 01668                    throw ParseError(errorPos, Res.InvalidIndex);
 1669                }
 1670
 01671                return Expression.ArrayIndex(expr, index);
 1672            }
 1673
 11674             switch (MethodFinder.FindIndexer(expr.Type, args, out var mb))
 1675            {
 1676                case 0:
 01677                    throw ParseError(errorPos, Res.NoApplicableIndexer,
 01678                        TypeHelper.GetTypeName(expr.Type));
 1679                case 1:
 11680                    return Expression.Call(expr, (MethodInfo)mb, args);
 1681
 1682        static bool IsPredefinedType(Type type)
 241683        {
 381684             if (_predefinedTypes.ContainsKey(type)) return true;
 1685
 101686             if (GlobalConfig.CustomTypeProvider != null && GlobalConfig.CustomTypeProvider.GetCustomTypes().Contains(typ
 1687
 101688            return false;
 241689        }
 1682                default:
 01683                    throw ParseError(errorPos, Res.AmbiguousIndexerInvocation, TypeHelper.GetTypeName(expr.Type));
 1684            }
 11685        }
 1686
 1687        internal static Type ToNullableType(Type type)
 41688        {
 41689            Check.NotNull(type, nameof(type));
 1690
 1691        public static bool IsNullableType(Type type)
 117521692        {
 117521693            return type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
 117521694        }
 41691             if (!type.GetTypeInfo().IsValueType || TypeHelper.IsNullableType(type))
 01692            {
 01693                throw ParseError(-1, Res.TypeHasNoNullableForm, TypeHelper.GetTypeName(type));
 1694            }
 1695
 1696        public static Type ToNullableType(Type type)
 21697        {
 21698             if (!type.GetTypeInfo().IsValueType || IsNullableType(type))
 01699                throw ParseError(-1, Res.TypeHasNoNullableForm, GetTypeName(type));
 1700
 21701            return typeof(Nullable<>).MakeGenericType(type);
 21702        }
 1703
 1704        static Type GetNonNullableType(Type type)
 116841705        {
 116841706             return IsNullableType(type) ? type.GetTypeInfo().GetGenericTypeArguments()[0] : type;
 116841707        }
 1708
 1709        static string GetTypeName(Type type)
 181710        {
 181711            Type baseType = GetNonNullableType(type);
 181712            string s = baseType.Name;
 181713             if (type != baseType) s += '?';
 181714            return s;
 181715        }
 1716
 1717        static bool TryGetMemberName(Expression expression, out string memberName)
 331718        {
 331719            var memberExpression = expression as MemberExpression;
 331720             if (memberExpression == null && expression.NodeType == ExpressionType.Coalesce)
 01721            {
 01722                memberExpression = (expression as BinaryExpression).Left as MemberExpression;
 01723            }
 41696            return typeof(Nullable<>).MakeGenericType(type);
 41697        }
 1698
 1699        static bool TryGetMemberName(Expression expression, out string memberName)
 371700        {
 371701            var memberExpression = expression as MemberExpression;
 371702             if (memberExpression == null && expression.NodeType == ExpressionType.Coalesce)
 01703            {
 01704                memberExpression = (expression as BinaryExpression).Left as MemberExpression;
 01705            }
 1706
 371707             if (memberExpression != null)
 371708            {
 371709                memberName = memberExpression.Member.Name;
 371710                return true;
 1711            }
 1712
 1713#if NETFX_CORE
 1714            var indexExpression = expression as IndexExpression;
 1715            if (indexExpression != null && indexExpression.Indexer.DeclaringType == typeof(DynamicObjectClass))
 1716            {
 1717                memberName = ((ConstantExpression)indexExpression.Arguments.First()).Value as string;
 1718                return true;
 1719            }
 1720#endif
 01721            memberName = null;
 01722            return false;
 371723        }
 1724
 331725             if (memberExpression != null)
 331726            {
 331727                memberName = memberExpression.Member.Name;
 331728                return true;
 1729            }
 1730
 1731#if NETFX_CORE
 1732            var indexExpression = expression as IndexExpression;
 1733            if (indexExpression != null && indexExpression.Indexer.DeclaringType == typeof(DynamicObjectClass))
 1734            {
 1735                memberName = ((ConstantExpression)indexExpression.Arguments.First()).Value as string;
 1736                return true;
 1737            }
 1738#endif
 1739            //#if !NET35
 1740            //            var dynamicExpression = expression as Expressions.DynamicExpression;
 1741            //            if (dynamicExpression != null)
 1742            //            {
 1743            //                memberName = ((GetMemberBinder)dynamicExpression.Binder).Name;
 1744            //                return true;
 1745            //            }
 1746            //#endif
 1747
 01748            memberName = null;
 01749            return false;
 331750        }
 1751
 1752        static bool IsNumericType(Type type)
 101753        {
 101754            return GetNumericTypeKind(type) != 0;
 101755        }
 1756
 1757        static bool IsSignedIntegralType(Type type)
 1921758        {
 1921759            return GetNumericTypeKind(type) == 2;
 1921760        }
 1761
 1762        static bool IsUnsignedIntegralType(Type type)
 1281763        {
 1281764            return GetNumericTypeKind(type) == 3;
 1281765        }
 1766
 1767        static int GetNumericTypeKind(Type type)
 3301768        {
 3301769            type = GetNonNullableType(type);
 1770#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 1771            if (type.GetTypeInfo().IsEnum) return 0;
 1772
 1773            switch (Type.GetTypeCode(type))
 1774            {
 1775                case TypeCode.Char:
 1776                case TypeCode.Single:
 1777                case TypeCode.Double:
 1778                case TypeCode.Decimal:
 1779                    return 1;
 1780                case TypeCode.SByte:
 1781                case TypeCode.Int16:
 1782                case TypeCode.Int32:
 1783                case TypeCode.Int64:
 1784                    return 2;
 1785                case TypeCode.Byte:
 1786                case TypeCode.UInt16:
 1787                case TypeCode.UInt32:
 1788                case TypeCode.UInt64:
 1789                    return 3;
 1790                default:
 1791                    return 0;
 1792            }
 1793#else
 3301794             if (type.GetTypeInfo().IsEnum) return 0;
 1725        void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos)
 01726        {
 01727            Expression[] args = { expr };
 1728
 01729             if (!MethodFinder.ContainsMethod(signatures, "F", false, args))
 01730            {
 01731                throw IncompatibleOperandError(opName, expr, errorPos);
 1732            }
 1733
 01734            expr = args[0];
 01735        }
 1736
 1737        void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int erro
 1471738        {
 1471739            Expression[] args = { left, right };
 1740
 1471741             if (!MethodFinder.ContainsMethod(signatures, "F", false, args))
 41742            {
 41743                throw IncompatibleOperandsError(opName, left, right, errorPos);
 1744            }
 1745
 1431746            left = args[0];
 1431747            right = args[1];
 1431748        }
 1749
 1750        static Exception IncompatibleOperandError(string opName, Expression expr, int errorPos)
 01751        {
 01752            return ParseError(errorPos, Res.IncompatibleOperand, opName, TypeHelper.GetTypeName(expr.Type));
 01753        }
 1754
 1755        static Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int errorPos)
 41756        {
 41757            return ParseError(errorPos, Res.IncompatibleOperands, opName, TypeHelper.GetTypeName(left.Type), TypeHelper.
 41758        }
 1759
 1760        static MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
 4391761        {
 1762#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 1763            BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | (staticAccess ? BindingFlags.Static :
 1764            foreach (Type t in TypeHelper.GetSelfAndBaseTypes(type))
 1765            {
 1766                MemberInfo[] members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, flags, Type.FilterNameIgn
 1767                if (members.Length != 0)
 1768                {
 1769                    return members[0];
 1770                }
 1771            }
 1772            return null;
 1773#else
 18501774            foreach (Type t in TypeHelper.GetSelfAndBaseTypes(type))
 4731775            {
 1776                // Try to find a property with the specified memberName
 18511777                MemberInfo member = t.GetTypeInfo().DeclaredProperties.FirstOrDefault(x => x.Name.ToLowerInvariant() == 
 4731778                 if (member != null)
 4131779                {
 4131780                    return member;
 1781                }
 1782
 1783                // If no property is found, try to get a field with the specified memberName
 1881784                 member = t.GetTypeInfo().DeclaredFields.FirstOrDefault(x => (x.IsStatic || !staticAccess) && x.Name.ToLo
 601785                 if (member != null)
 01786                {
 01787                    return member;
 1788                }
 1789
 1790                // No property or field is found, try the base type.
 601791            }
 261792            return null;
 1793#endif
 4391794        }
 1795
 3301796             if (type == typeof(Char) || type == typeof(Single) || type == typeof(Double) || type == typeof(Decimal))
 21797                return 1;
 3281798             if (type == typeof(SByte) || type == typeof(Int16) || type == typeof(Int32) || type == typeof(Int64))
 1331799                return 2;
 1951800             if (type == typeof(Byte) || type == typeof(UInt16) || type == typeof(UInt32) || type == typeof(UInt64))
 1951801                return 3;
 01802            return 0;
 1803#endif
 3301804        }
 1805
 1806        static bool IsEnumType(Type type)
 2781807        {
 2781808            return GetNonNullableType(type).GetTypeInfo().IsEnum;
 2781809        }
 1810
 1811        void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos)
 01812        {
 01813            Expression[] args = { expr };
 1814            MethodBase method;
 01815             if (FindMethod(signatures, "F", false, args, out method) != 1)
 01816                throw ParseError(errorPos, Res.IncompatibleOperand, opName, GetTypeName(args[0].Type));
 1796        bool TokenIdentifierIs(string id)
 48401797        {
 48401798            return _textParser.CurrentToken.Id == TokenId.Identifier && string.Equals(id, _textParser.CurrentToken.Text,
 48401799        }
 1800
 1801        string GetIdentifier()
 6231802        {
 6231803            _textParser.ValidateToken(TokenId.Identifier, Res.IdentifierExpected);
 6231804            string id = _textParser.CurrentToken.Text;
 6231805             if (id.Length > 1 && id[0] == '@')
 01806            {
 01807                id = id.Substring(1);
 01808            }
 1809
 6231810            return id;
 6231811        }
 1812
 1813        Exception ParseError(string format, params object[] args)
 71814        {
 71815             return ParseError(_textParser?.CurrentToken.Pos ?? 0, format, args);
 71816        }
 1817
 01818            expr = args[0];
 01819        }
 1820
 1821        void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int erro
 1841822        {
 1841823            Expression[] args = { left, right };
 1824
 1825            MethodBase method;
 1841826             if (FindMethod(signatures, "F", false, args, out method) != 1)
 41827                throw IncompatibleOperandsError(opName, left, right, errorPos);
 1828
 1801829            left = args[0];
 1801830            right = args[1];
 1801831        }
 1832
 1833        static Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos)
 41834        {
 41835            return ParseError(pos, Res.IncompatibleOperands, opName, GetTypeName(left.Type), GetTypeName(right.Type));
 41836        }
 1837
 1838        static MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
 3191839        {
 1840#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 1841            BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | (staticAccess ? BindingFlags.Static :
 1842            foreach (Type t in SelfAndBaseTypes(type))
 1843            {
 1844                MemberInfo[] members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, flags, Type.FilterNameIgn
 1845                if (members.Length != 0)
 1846                    return members[0];
 1847            }
 1848            return null;
 1849#else
 13331850            foreach (Type t in SelfAndBaseTypes(type))
 3401851            {
 1852                // Try to find a property with the specified memberName
 13191853                MemberInfo member = t.GetTypeInfo().DeclaredProperties.FirstOrDefault(x => x.Name.ToLowerInvariant() == 
 3401854                 if (member != null)
 3041855                    return member;
 1856
 1857                // If no property is found, try to get a field with the specified memberName
 1081858                 member = t.GetTypeInfo().DeclaredFields.FirstOrDefault(x => (x.IsStatic || !staticAccess) && x.Name.ToLo
 361859                 if (member != null)
 01860                    return member;
 1861
 1862                // No property or field is found, try the base type.
 361863            }
 151864            return null;
 1865#endif
 3191866        }
 1867
 1868        int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method)
 2541869        {
 1870#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 1871            BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
 1872                (staticAccess ? BindingFlags.Static : BindingFlags.Instance);
 1873            foreach (Type t in SelfAndBaseTypes(type))
 1874            {
 1875                MemberInfo[] members = t.FindMembers(MemberTypes.Method,
 1876                    flags, Type.FilterNameIgnoreCase, methodName);
 1877                int count = FindBestMethod(members.Cast<MethodBase>(), args, out method);
 1878                if (count != 0) return count;
 1879            }
 1880            method = null;
 1881            return 0;
 1882#else
 13781883            foreach (Type t in SelfAndBaseTypes(type))
 4331884            {
 81231885                 MethodInfo[] methods = t.GetTypeInfo().DeclaredMethods.Where(x => (x.IsStatic || !staticAccess) && x.Nam
 4331886                int count = FindBestMethod(methods, args, out method);
 6831887                 if (count != 0) return count;
 1831888            }
 1889
 41890            method = null;
 41891            return 0;
 1892#endif
 2541893        }
 1894
 1895        int FindIndexer(Type type, Expression[] args, out MethodBase method)
 11896        {
 41897            foreach (Type t in SelfAndBaseTypes(type))
 11898            {
 1899                //#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 11900                MemberInfo[] members = t.GetDefaultMembers();
 1901                //#else
 1902                //                MemberInfo[] members = new MemberInfo[0];
 1903                //#endif
 11904                 if (members.Length != 0)
 11905                {
 11906                    IEnumerable<MethodBase> methods = members
 11907                        .OfType<PropertyInfo>().
 11908#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 11909                        Select(p => (MethodBase)p.GetGetMethod()).
 11910                        Where(m => m != null);
 11911#else
 31912                    Select(p => (MethodBase)p.GetMethod);
 1913#endif
 1914
 11915                    int count = FindBestMethod(methods, args, out method);
 21916                     if (count != 0) return count;
 01917                }
 01918            }
 01919            method = null;
 01920            return 0;
 11921        }
 1922
 1923        static IEnumerable<Type> SelfAndBaseTypes(Type type)
 5741924        {
 5741925             if (type.GetTypeInfo().IsInterface)
 2511926            {
 2511927                List<Type> types = new List<Type>();
 2511928                AddInterface(types, type);
 2511929                return types;
 1930            }
 3231931            return SelfAndBaseClasses(type);
 5741932        }
 1933
 1934        static IEnumerable<Type> SelfAndBaseClasses(Type type)
 3231935        {
 3531936             while (type != null)
 3401937            {
 3401938                yield return type;
 301939                type = type.GetTypeInfo().BaseType;
 301940            }
 131941        }
 1942
 1943        static void AddInterface(List<Type> types, Type type)
 5321944        {
 5321945             if (!types.Contains(type))
 4561946            {
 4561947                types.Add(type);
 22111948                foreach (Type t in type.GetInterfaces()) AddInterface(types, t);
 4561949            }
 5321950        }
 1951
 1952        class MethodData
 1953        {
 1954            public MethodBase MethodBase;
 1955            public ParameterInfo[] Parameters;
 1956            public Expression[] Args;
 1957        }
 1958
 1959        int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method)
 4411960        {
 4411961            MethodData[] applicable = methods.
 44891962                Select(m => new MethodData { MethodBase = m, Parameters = m.GetParameters() }).
 44891963                Where(m => IsApplicable(m, args)).
 4411964                ToArray();
 1965
 4411966             if (applicable.Length > 1)
 1841967            {
 43211968                applicable = applicable.Where(m => applicable.All(n => m == n || IsBetterThan(args, m, n))).ToArray();
 1841969            }
 1970
 4411971             if (applicable.Length == 1)
 2521972            {
 2521973                MethodData md = applicable[0];
 17551974                 for (int i = 0; i < args.Length; i++) args[i] = md.Args[i];
 2521975                method = md.MethodBase;
 2521976            }
 1977            else
 1891978            {
 1891979                method = null;
 1891980            }
 1981
 4411982            return applicable.Length;
 4411983        }
 1984
 1985        bool IsApplicable(MethodData method, Expression[] args)
 40481986        {
 40711987             if (method.Parameters.Length != args.Length) return false;
 40251988            Expression[] promotedArgs = new Expression[args.Length];
 139461989             for (int i = 0; i < args.Length; i++)
 54651990            {
 54651991                ParameterInfo pi = method.Parameters[i];
 54651992                 if (pi.IsOut) return false;
 54651993                Expression promoted = PromoteExpression(args[i], pi.ParameterType, false, method.MethodBase.DeclaringTyp
 79821994                 if (promoted == null) return false;
 29481995                promotedArgs[i] = promoted;
 29481996            }
 15081997            method.Args = promotedArgs;
 15081998            return true;
 40481999        }
 2000
 2001        Expression PromoteExpression(Expression expr, Type type, bool exact, bool convertExpr)
 56712002        {
 56712003             if (expr.Type == type)
 6642004                return expr;
 2005
 50072006            var ce = expr as ConstantExpression;
 2007
 50072008             if (ce != null)
 11692009            {
 11692010                 if (ce == NullLiteral)
 392011                {
 392012                     if (!type.GetTypeInfo().IsValueType || IsNullableType(type))
 232013                        return Expression.Constant(null, type);
 162014                }
 2015                else
 11302016                {
 2017                    string text;
 11302018                     if (_literals.TryGetValue(ce, out text))
 9752019                    {
 9752020                        Type target = GetNonNullableType(type);
 9752021                        object value = null;
 2022
 2023#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 2024                        switch (Type.GetTypeCode(ce.Type))
 2025                        {
 2026                            case TypeCode.Int32:
 2027                            case TypeCode.UInt32:
 2028                            case TypeCode.Int64:
 2029                            case TypeCode.UInt64:
 2030                                value = ParseNumber(text, target);
 2031
 2032                                // Make sure an enum value stays an enum value
 2033                                if (target.IsEnum)
 2034                                    value = Enum.ToObject(target, value);
 2035                                break;
 2036
 2037                            case TypeCode.Double:
 2038                                if (target == typeof(decimal)) value = ParseNumber(text, target);
 2039                                break;
 2040
 2041                            case TypeCode.String:
 2042                                value = ParseEnum(text, target);
 2043                                break;
 2044                        }
 2045#else
 9752046                         if (ce.Type == typeof(Int32) || ce.Type == typeof(UInt32) || ce.Type == typeof(Int64) || ce.Type
 9472047                        {
 9472048                            value = ParseNumber(text, target);
 2049
 2050                            // Make sure an enum value stays an enum value
 9472051                             if (target.GetTypeInfo().IsEnum)
 02052                                value = Enum.ToObject(target, value);
 9472053                        }
 282054                         else if (ce.Type == typeof(Double))
 152055                        {
 152056                             if (target == typeof(decimal)) value = ParseNumber(text, target);
 152057                        }
 132058                         else if (ce.Type == typeof(String))
 12059                        {
 12060                            value = ParseEnum(text, target);
 12061                        }
 2062#endif
 9752063                         if (value != null)
 8532064                            return Expression.Constant(value, type);
 1222065                    }
 2772066                }
 2932067            }
 2068
 41312069             if (IsCompatibleWith(expr.Type, type))
 15912070            {
 15912071                 if (type.GetTypeInfo().IsValueType || exact || (expr.Type.GetTypeInfo().IsValueType && convertExpr))
 15652072                    return Expression.Convert(expr, type);
 2073
 262074                return expr;
 2075            }
 2076
 25402077            return null;
 56712078        }
 2079
 2080        static object ParseNumber(string text, Type type)
 9472081        {
 2082#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 2083            switch (Type.GetTypeCode(GetNonNullableType(type)))
 2084            {
 2085                case TypeCode.SByte:
 2086                    sbyte sb;
 2087                    if (sbyte.TryParse(text, out sb)) return sb;
 2088                    break;
 2089                case TypeCode.Byte:
 2090                    byte b;
 2091                    if (byte.TryParse(text, out b)) return b;
 2092                    break;
 2093                case TypeCode.Int16:
 2094                    short s;
 2095                    if (short.TryParse(text, out s)) return s;
 2096                    break;
 2097                case TypeCode.UInt16:
 2098                    ushort us;
 2099                    if (ushort.TryParse(text, out us)) return us;
 2100                    break;
 2101                case TypeCode.Int32:
 2102                    int i;
 2103                    if (int.TryParse(text, out i)) return i;
 2104                    break;
 2105                case TypeCode.UInt32:
 2106                    uint ui;
 2107                    if (uint.TryParse(text, out ui)) return ui;
 2108                    break;
 2109                case TypeCode.Int64:
 2110                    long l;
 2111                    if (long.TryParse(text, out l)) return l;
 2112                    break;
 2113                case TypeCode.UInt64:
 2114                    ulong ul;
 2115                    if (ulong.TryParse(text, out ul)) return ul;
 2116                    break;
 2117                case TypeCode.Single:
 2118                    float f;
 2119                    if (float.TryParse(text, out f)) return f;
 2120                    break;
 2121                case TypeCode.Double:
 2122                    double d;
 2123                    if (double.TryParse(text, out d)) return d;
 2124                    break;
 2125                case TypeCode.Decimal:
 2126                    decimal e;
 2127                    if (decimal.TryParse(text, out e)) return e;
 2128                    break;
 2129            }
 2130#else
 9472131            var tp = GetNonNullableType(type);
 9472132             if (tp == typeof(SByte))
 02133            {
 2134                sbyte sb;
 02135                 if (sbyte.TryParse(text, out sb)) return sb;
 02136            }
 9472137             else if (tp == typeof(Byte))
 02138            {
 2139                byte b;
 02140                 if (byte.TryParse(text, out b)) return b;
 02141            }
 9472142             else if (tp == typeof(Int16))
 02143            {
 2144                short s;
 02145                 if (short.TryParse(text, out s)) return s;
 02146            }
 9472147             else if (tp == typeof(UInt16))
 02148            {
 2149                ushort us;
 02150                 if (ushort.TryParse(text, out us)) return us;
 02151            }
 9472152             else if (tp == typeof(Int32))
 1882153            {
 2154                int i;
 3702155                 if (int.TryParse(text, out i)) return i;
 62156            }
 7592157             else if (tp == typeof(UInt32))
 172158            {
 2159                uint ui;
 342160                 if (uint.TryParse(text, out ui)) return ui;
 02161            }
 7422162             else if (tp == typeof(Int64))
 1552163            {
 2164                long l;
 3042165                 if (long.TryParse(text, out l)) return l;
 62166            }
 5872167             else if (tp == typeof(UInt64))
 232168            {
 2169                ulong ul;
 452170                 if (ulong.TryParse(text, out ul)) return ul;
 12171            }
 5642172             else if (tp == typeof(Single))
 1682173            {
 2174                float f;
 3262175                 if (float.TryParse(text, out f)) return f;
 102176            }
 3962177             else if (tp == typeof(Double))
 1802178            {
 2179                double d;
 3502180                 if (double.TryParse(text, out d)) return d;
 102181            }
 2162182             else if (tp == typeof(Decimal))
 1652183            {
 2184                decimal e;
 3202185                 if (decimal.TryParse(text, out e)) return e;
 102186            }
 2187#endif
 942188            return null;
 9472189        }
 2190
 2191        static object ParseEnum(string value, Type type)
 12192        {
 2193#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 2194            if (type.IsEnum)
 2195            {
 2196                MemberInfo[] memberInfos = type.FindMembers(MemberTypes.Field,
 2197                    BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static,
 2198                    Type.FilterNameIgnoreCase, value);
 2199
 2200                if (memberInfos.Length != 0)
 2201                    return ((FieldInfo)memberInfos[0]).GetValue(null);
 2202            }
 2203#else
 12204             if (type.GetTypeInfo().IsEnum)
 02205            {
 02206                return Enum.Parse(type, value, true);
 2207            }
 2208#endif
 12209            return null;
 12210        }
 2211
 2212        static bool IsCompatibleWith(Type source, Type target)
 48432213        {
 2214#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 2215            if (source == target) return true;
 2216            if (!target.IsValueType) return target.IsAssignableFrom(source);
 2217            Type st = GetNonNullableType(source);
 2218            Type tt = GetNonNullableType(target);
 2219            if (st != source && tt == target) return false;
 2220            TypeCode sc = st.GetTypeInfo().IsEnum ? TypeCode.Object : Type.GetTypeCode(st);
 2221            TypeCode tc = tt.GetTypeInfo().IsEnum ? TypeCode.Object : Type.GetTypeCode(tt);
 2222            switch (sc)
 2223            {
 2224                case TypeCode.SByte:
 2225                    switch (tc)
 2226                    {
 2227                        case TypeCode.SByte:
 2228                        case TypeCode.Int16:
 2229                        case TypeCode.Int32:
 2230                        case TypeCode.Int64:
 2231                        case TypeCode.Single:
 2232                        case TypeCode.Double:
 2233                        case TypeCode.Decimal:
 2234                            return true;
 2235                    }
 2236                    break;
 2237                case TypeCode.Byte:
 2238                    switch (tc)
 2239                    {
 2240                        case TypeCode.Byte:
 2241                        case TypeCode.Int16:
 2242                        case TypeCode.UInt16:
 2243                        case TypeCode.Int32:
 2244                        case TypeCode.UInt32:
 2245                        case TypeCode.Int64:
 2246                        case TypeCode.UInt64:
 2247                        case TypeCode.Single:
 2248                        case TypeCode.Double:
 2249                        case TypeCode.Decimal:
 2250                            return true;
 2251                    }
 2252                    break;
 2253                case TypeCode.Int16:
 2254                    switch (tc)
 2255                    {
 2256                        case TypeCode.Int16:
 2257                        case TypeCode.Int32:
 2258                        case TypeCode.Int64:
 2259                        case TypeCode.Single:
 2260                        case TypeCode.Double:
 2261                        case TypeCode.Decimal:
 2262                            return true;
 2263                    }
 2264                    break;
 2265                case TypeCode.UInt16:
 2266                    switch (tc)
 2267                    {
 2268                        case TypeCode.UInt16:
 2269                        case TypeCode.Int32:
 2270                        case TypeCode.UInt32:
 2271                        case TypeCode.Int64:
 2272                        case TypeCode.UInt64:
 2273                        case TypeCode.Single:
 2274                        case TypeCode.Double:
 2275                        case TypeCode.Decimal:
 2276                            return true;
 2277                    }
 2278                    break;
 2279                case TypeCode.Int32:
 2280                    switch (tc)
 2281                    {
 2282                        case TypeCode.Int32:
 2283                        case TypeCode.Int64:
 2284                        case TypeCode.Single:
 2285                        case TypeCode.Double:
 2286                        case TypeCode.Decimal:
 2287                            return true;
 2288                    }
 2289                    break;
 2290                case TypeCode.UInt32:
 2291                    switch (tc)
 2292                    {
 2293                        case TypeCode.UInt32:
 2294                        case TypeCode.Int64:
 2295                        case TypeCode.UInt64:
 2296                        case TypeCode.Single:
 2297                        case TypeCode.Double:
 2298                        case TypeCode.Decimal:
 2299                            return true;
 2300                    }
 2301                    break;
 2302                case TypeCode.Int64:
 2303                    switch (tc)
 2304                    {
 2305                        case TypeCode.Int64:
 2306                        case TypeCode.Single:
 2307                        case TypeCode.Double:
 2308                        case TypeCode.Decimal:
 2309                            return true;
 2310                    }
 2311                    break;
 2312                case TypeCode.UInt64:
 2313                    switch (tc)
 2314                    {
 2315                        case TypeCode.UInt64:
 2316                        case TypeCode.Single:
 2317                        case TypeCode.Double:
 2318                        case TypeCode.Decimal:
 2319                            return true;
 2320                    }
 2321                    break;
 2322                case TypeCode.Single:
 2323                    switch (tc)
 2324                    {
 2325                        case TypeCode.Single:
 2326                        case TypeCode.Double:
 2327                            return true;
 2328                    }
 2329                    break;
 2330                default:
 2331                    if (st == tt) return true;
 2332                    break;
 2333            }
 2334            return false;
 2335#else
 48432336             if (source == target) return true;
 51232337             if (!target.GetTypeInfo().IsValueType) return target.IsAssignableFrom(source);
 45632338            Type st = GetNonNullableType(source);
 45632339            Type tt = GetNonNullableType(target);
 47922340             if (st != source && tt == target) return false;
 43342341             Type sc = st.GetTypeInfo().IsEnum ? typeof(Object) : st;
 43342342             Type tc = tt.GetTypeInfo().IsEnum ? typeof(Object) : tt;
 2343
 43342344             if (sc == typeof(SByte))
 642345            {
 642346                 if (tc == typeof(SByte) || tc == typeof(Int16) || tc == typeof(Int32) || tc == typeof(Int64) || tc == ty
 322347                    return true;
 322348            }
 42702349             else if (sc == typeof(Byte))
 652350            {
 652351                 if (tc == typeof(Byte) || tc == typeof(Int16) || tc == typeof(UInt16) || tc == typeof(Int32) || tc == ty
 652352                    return true;
 02353            }
 42052354             else if (sc == typeof(Int16))
 652355            {
 652356                 if (tc == typeof(Int16) || tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == t
 332357                    return true;
 322358            }
 41402359             else if (sc == typeof(UInt16))
 642360            {
 642361                 if (tc == typeof(UInt16) || tc == typeof(Int32) || tc == typeof(UInt32) || tc == typeof(Int64) || tc == 
 642362                    return true;
 02363            }
 40762364             else if (sc == typeof(Int32))
 25602365            {
 25602366                 if (tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == 
 12762367                    return true;
 12842368            }
 15162369             else if (sc == typeof(UInt32))
 1552370            {
 1552371                 if (tc == typeof(UInt32) || tc == typeof(Int64) || tc == typeof(UInt64) || tc == typeof(Single) || tc ==
 732372                    return true;
 822373            }
 13612374             else if (sc == typeof(Int64))
 2622375            {
 2622376                 if (tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
 782377                    return true;
 1842378            }
 10992379             else if (sc == typeof(UInt64))
 1622380            {
 1622381                 if (tc == typeof(UInt64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
 362382                    return true;
 1262383            }
 9372384             else if (sc == typeof(Single))
 2502385            {
 2502386                 if (tc == typeof(Single) || tc == typeof(Double))
 402387                    return true;
 2102388            }
 2389
 26372390             if (st == tt)
 922391                return true;
 25452392            return false;
 2393#endif
 48432394        }
 2395
 2396        static bool IsBetterThan(Expression[] args, MethodData first, MethodData second)
 25122397        {
 25122398            bool better = false;
 51522399             for (int i = 0; i < args.Length; i++)
 25762400            {
 25762401                CompareConversionType result = CompareConversions(args[i].Type, first.Parameters[i].ParameterType, secon
 2402
 2403                // If second is better, return false
 25762404                 if (result == CompareConversionType.Second)
 12562405                    return false;
 2406
 2407                // If first is better, return true
 13202408                 if (result == CompareConversionType.First)
 12562409                    return true;
 2410
 2411                // If both are same, just set better to true and continue
 642412                 if (result == CompareConversionType.Both)
 642413                    better = true;
 642414            }
 2415
 02416            return better;
 25122417        }
 2418
 2419        enum CompareConversionType
 2420        {
 2421            Both = 0,
 2422            First = 1,
 2423            Second = -1
 2424        }
 2425
 2426        // Return "First" if s -> t1 is a better conversion than s -> t2
 2427        // Return "Second" if s -> t2 is a better conversion than s -> t1
 2428        // Return "Both" if neither conversion is better
 2429        static CompareConversionType CompareConversions(Type source, Type first, Type second)
 25762430        {
 26402431             if (first == second) return CompareConversionType.Both;
 35902432             if (source == first) return CompareConversionType.First;
 25122433             if (source == second) return CompareConversionType.Second;
 2434
 3562435            bool firstIsCompatibleWithSecond = IsCompatibleWith(first, second);
 3562436            bool secondIsCompatibleWithFirst = IsCompatibleWith(second, first);
 2437
 4702438             if (firstIsCompatibleWithSecond && !secondIsCompatibleWithFirst) return CompareConversionType.First;
 3562439             if (secondIsCompatibleWithFirst && !firstIsCompatibleWithSecond) return CompareConversionType.Second;
 2440
 1922441             if (IsSignedIntegralType(first) && IsUnsignedIntegralType(second)) return CompareConversionType.First;
 1282442             if (IsSignedIntegralType(second) && IsUnsignedIntegralType(first)) return CompareConversionType.Second;
 2443
 02444            return CompareConversionType.Both;
 25762445        }
 2446
 2447        static Expression GenerateEqual(Expression left, Expression right)
 1332448        {
 1332449            OptimizeForEqualityIfPossible(ref left, ref right);
 1332450            return Expression.Equal(left, right);
 1332451        }
 2452
 2453        static Expression GenerateNotEqual(Expression left, Expression right)
 62454        {
 62455            OptimizeForEqualityIfPossible(ref left, ref right);
 62456            return Expression.NotEqual(left, right);
 62457        }
 2458
 2459        static Expression GenerateGreaterThan(Expression left, Expression right)
 382460        {
 382461             if (left.Type == typeof(string))
 12462            {
 12463                return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
 2464            }
 2465
 372466             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 12467            {
 12468                 var leftPart = left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetUnderlyingType(left.Typ
 12469                 var rightPart = right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right
 12470                return Expression.GreaterThan(leftPart, rightPart);
 2471            }
 2472
 362473            return Expression.GreaterThan(left, right);
 382474        }
 2475
 2476        static Expression GenerateGreaterThanEqual(Expression left, Expression right)
 32477        {
 32478             if (left.Type == typeof(string))
 12479            {
 12480                return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Consta
 2481            }
 2482
 22483             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 12484            {
 12485                 return Expression.GreaterThanOrEqual(left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetU
 12486                    right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right.Type)) : ri
 2487            }
 2488
 12489            return Expression.GreaterThanOrEqual(left, right);
 32490        }
 2491
 2492        static Expression GenerateLessThan(Expression left, Expression right)
 52493        {
 52494             if (left.Type == typeof(string))
 12495            {
 12496                return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
 2497            }
 2498
 42499             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 12500            {
 12501                 return Expression.LessThan(left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetUnderlyingT
 12502                    right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right.Type)) : ri
 2503            }
 2504
 32505            return Expression.LessThan(left, right);
 52506        }
 2507
 2508        static Expression GenerateLessThanEqual(Expression left, Expression right)
 42509        {
 42510             if (left.Type == typeof(string))
 12511            {
 12512                return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(
 2513            }
 2514
 32515             if (left.Type.GetTypeInfo().IsEnum || right.Type.GetTypeInfo().IsEnum)
 12516            {
 12517                 return Expression.LessThanOrEqual(left.Type.GetTypeInfo().IsEnum ? Expression.Convert(left, Enum.GetUnde
 12518                    right.Type.GetTypeInfo().IsEnum ? Expression.Convert(right, Enum.GetUnderlyingType(right.Type)) : ri
 2519            }
 2520
 22521            return Expression.LessThanOrEqual(left, right);
 42522        }
 2523
 2524        static Expression GenerateAdd(Expression left, Expression right)
 112525        {
 112526             if (left.Type == typeof(string) && right.Type == typeof(string))
 02527            {
 02528                return GenerateStaticMethodCall("Concat", left, right);
 2529            }
 112530            return Expression.Add(left, right);
 112531        }
 2532
 2533        static Expression GenerateSubtract(Expression left, Expression right)
 02534        {
 02535            return Expression.Subtract(left, right);
 02536        }
 2537
 2538        static Expression GenerateStringConcat(Expression left, Expression right)
 102539        {
 2540            // Allow concat String with something else
 102541            return Expression.Call(null, typeof(string).GetMethod("Concat", new[] { left.Type, right.Type }), new[] { le
 102542        }
 2543
 2544        static MethodInfo GetStaticMethod(string methodName, Expression left, Expression right)
 42545        {
 42546            return left.Type.GetMethod(methodName, new[] { left.Type, right.Type });
 42547        }
 2548
 2549        static Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right)
 42550        {
 42551            return Expression.Call(null, GetStaticMethod(methodName, left, right), new[] { left, right });
 42552        }
 2553
 2554        static void OptimizeForEqualityIfPossible(ref Expression left, ref Expression right)
 1392555        {
 2556            // The goal here is to provide the way to convert some types from the string form in a way that is compatibl
 2557            //
 2558            // The Expression.Call(typeof(Guid).GetMethod("Parse"), right); does the job only for Linq to Object but Lin
 2559            //
 1392560            Type leftType = left.Type;
 1392561            Type rightType = right.Type;
 2562
 1392563             if (rightType == typeof(string) && right.NodeType == ExpressionType.Constant)
 192564            {
 192565                 right = OptimizeStringForEqualityIfPossible((string)((ConstantExpression)right).Value, leftType) ?? righ
 192566            }
 2567
 1392568             if (leftType == typeof(string) && left.NodeType == ExpressionType.Constant)
 02569            {
 02570                 left = OptimizeStringForEqualityIfPossible((string)((ConstantExpression)left).Value, rightType) ?? left;
 02571            }
 1392572        }
 2573
 2574        static Expression OptimizeStringForEqualityIfPossible(string text, Type type)
 192575        {
 2576            DateTime dateTime;
 2577
 192578             if (type == typeof(DateTime) &&
 192579                DateTime.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
 02580                return Expression.Constant(dateTime, typeof(DateTime));
 2581#if !NET35
 2582            Guid guid;
 192583             if (type == typeof(Guid) && Guid.TryParse(text, out guid))
 02584                return Expression.Constant(guid, typeof(Guid));
 2585#else
 2586            try
 2587            {
 2588                return Expression.Constant(new Guid(text));
 2589            }
 2590            catch
 2591            {
 2592                //Doing it in old fashion way when no TryParse interface was provided by .NET
 2593            }
 2594#endif
 192595            return null;
 192596        }
 2597
 2598        bool TokenIdentifierIs(string id)
 34992599        {
 34992600            return _textParser.CurrentToken.Id == TokenId.Identifier && string.Equals(id, _textParser.CurrentToken.Text,
 34992601        }
 2602
 2603        string GetIdentifier()
 4422604        {
 4422605            _textParser.ValidateToken(TokenId.Identifier, Res.IdentifierExpected);
 4422606            string id = _textParser.CurrentToken.Text;
 4422607             if (id.Length > 1 && id[0] == '@') id = id.Substring(1);
 4422608            return id;
 4422609        }
 2610
 2611        Exception ParseError(string format, params object[] args)
 42612        {
 42613            return ParseError(_textParser.CurrentToken.Pos, format, args);
 42614        }
 2615
 2616        static Exception ParseError(int pos, string format, params object[] args)
 222617        {
 222618            return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos);
 222619        }
 2620
 2621        static Dictionary<string, object> CreateKeywords()
 132622        {
 132623            var d = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
 132624            {
 132625                {"true", TrueLiteral},
 132626                {"false", FalseLiteral},
 132627                {"null", NullLiteral}
 132628            };
 2629
 132630             if (GlobalConfig.AreContextKeywordsEnabled)
 122631            {
 122632                d.Add(KEYWORD_IT, KEYWORD_IT);
 122633                d.Add(KEYWORD_PARENT, KEYWORD_PARENT);
 122634                d.Add(KEYWORD_ROOT, KEYWORD_ROOT);
 122635            }
 2636
 132637            d.Add(SYMBOL_IT, SYMBOL_IT);
 132638            d.Add(SYMBOL_PARENT, SYMBOL_PARENT);
 132639            d.Add(SYMBOL_ROOT, SYMBOL_ROOT);
 132640            d.Add(KEYWORD_IIF, KEYWORD_IIF);
 132641            d.Add(KEYWORD_NEW, KEYWORD_NEW);
 132642            d.Add(KEYWORD_ISNULL, KEYWORD_ISNULL);
 2643
 11832644            foreach (Type type in _predefinedTypes.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key))
 2862645            {
 2862646                d[type.FullName] = type;
 2862647                d[type.Name] = type;
 2862648            }
 2649
 2472650            foreach (KeyValuePair<string, Type> pair in _predefinedTypesShorthands)
 1042651                d.Add(pair.Key, pair.Value);
 2652
 132653             if (GlobalConfig.CustomTypeProvider != null)
 102654            {
 502655                foreach (Type type in GlobalConfig.CustomTypeProvider.GetCustomTypes())
 102656                {
 102657                    d[type.FullName] = type;
 102658                    d[type.Name] = type;
 102659                }
 102660            }
 2661
 132662            return d;
 132663        }
 2664
 2665        internal static void ResetDynamicLinqTypes()
 72666        {
 72667            _keywords = null;
 72668        }
 2669    }
 2670}
 1818        static Exception ParseError(int pos, string format, params object[] args)
 221819        {
 221820            return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos);
 221821        }
 1822    }
 1823
 1824}
-
+

Methods/Properties

-.cctor()
-UpdatePredefinedTypes(System.String,System.Int32)
-.ctor(System.Linq.Expressions.ParameterExpression[],System.String,System.Object[])
-ProcessParameters(System.Linq.Expressions.ParameterExpression[])
-ProcessValues(System.Object[])
-AddSymbol(System.String,System.Object)
-Parse(System.Type,System.Boolean)
-ParseOrdering(System.Boolean)
-ParseConditionalOperator()
-ParseNullCoalescingOperator()
-ParseLambdaOperator()
-ParseIsNull()
-ParseOrOperator()
-ParseAndOperator()
-ParseIn()
-ParseLogicalAndOrOperator()
-ParseComparisonOperator()
-ParseEnumToConstantExpression(System.Int32,System.Type,System.Linq.Expressions.ConstantExpression)
-ParseConstantExpressionToEnum(System.Int32,System.Type,System.Linq.Expressions.ConstantExpression)
-ParseShiftOperator()
-ParseAdditive()
-ParseMultiplicative()
-ParseUnary()
-ParsePrimary()
-ParsePrimaryStart()
-ParseStringLiteral()
-ParseIntegerLiteral()
-ParseRealLiteral()
-TryParseAsFloat(System.String,System.Char)
-TryParseAsDouble(System.String,System.Char)
-CreateLiteral(System.Object,System.String)
-ParseParenExpression()
-ParseIdentifier()
-ParseIt()
-ParseParent()
-ParseRoot()
-ParseIif()
-GenerateConditional(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Int32)
-ParseNew()
-CreateArrayInitializerExpression(System.Collections.Generic.List`1<System.Linq.Expressions.Expression>,System.Type)
-CreateNewExpression(System.Collections.Generic.List`1<System.Linq.Dynamic.Core.DynamicProperty>,System.Collections.Generic.List`1<System.Linq.Expressions.Expression>,System.Type)
-ParseLambdaInvocation(System.Linq.Expressions.LambdaExpression)
-ParseTypeAccess(System.Type)
-GenerateConversion(System.Linq.Expressions.Expression,System.Type,System.Int32)
-ParseMemberAccess(System.Type,System.Linq.Expressions.Expression)
-FindGenericType(System.Type,System.Type)
-FindType(System.String)
-ParseAggregate(System.Linq.Expressions.Expression,System.Type,System.String,System.Int32)
-ParseArgumentList()
-ParseArguments()
+.cctor()
+.ctor(System.Linq.Expressions.ParameterExpression[],System.String,System.Object[],System.Linq.Dynamic.Core.ParsingConfig)
+ProcessParameters(System.Linq.Expressions.ParameterExpression[])
+ProcessValues(System.Object[])
+AddSymbol(System.String,System.Object)
+Parse(System.Type,System.Boolean)
+ParseOrdering(System.Boolean)
+ParseConditionalOperator()
+ParseNullCoalescingOperator()
+ParseLambdaOperator()
+ParseIsNull()
+ParseOrOperator()
+ParseAndOperator()
+ParseIn()
+ParseLogicalAndOrOperator()
+ParseComparisonOperator()
+HasImplicitConversion(System.Type,System.Type)
+ParseEnumToConstantExpression(System.Int32,System.Type,System.Linq.Expressions.ConstantExpression)
+ParseConstantExpressionToEnum(System.Int32,System.Type,System.Linq.Expressions.ConstantExpression)
+ParseShiftOperator()
+ParseAdditive()
+ParseMultiplicative()
+ParseUnary()
+ParsePrimary()
+ParsePrimaryStart()
+ParseStringLiteral()
+ParseIntegerLiteral()
+ParseRealLiteral()
+TryParseAsFloat(System.String,System.Char)
+TryParseAsDecimal(System.String,System.Char)
+TryParseAsDouble(System.String,System.Char)
+ParseParenExpression()
+ParseIdentifier()
+ParseIt()
+ParseParent()
+ParseRoot()
+ParseIif()
+GenerateConditional(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Int32)
+ParseNew()
+CreateArrayInitializerExpression(System.Collections.Generic.List`1<System.Linq.Expressions.Expression>,System.Type)
+CreateNewExpression(System.Collections.Generic.List`1<System.Linq.Dynamic.Core.DynamicProperty>,System.Collections.Generic.List`1<System.Linq.Expressions.Expression>,System.Type)
+ParseLambdaInvocation(System.Linq.Expressions.LambdaExpression)
+ParseTypeAccess(System.Type)
+GenerateConversion(System.Linq.Expressions.Expression,System.Type,System.Int32)
+ParseMemberAccess(System.Type,System.Linq.Expressions.Expression)
+FindType(System.String)
+ParseAggregate(System.Linq.Expressions.Expression,System.Type,System.String,System.Int32,System.Boolean)
+ParseArgumentList()
+ParseArguments()
ParseElementAccess(System.Linq.Expressions.Expression)
-IsPredefinedType(System.Type)
-IsNullableType(System.Type)
-ToNullableType(System.Type)
-GetNonNullableType(System.Type)
-GetTypeName(System.Type)
-TryGetMemberName(System.Linq.Expressions.Expression,System.String&)
-IsNumericType(System.Type)
-IsSignedIntegralType(System.Type)
-IsUnsignedIntegralType(System.Type)
-GetNumericTypeKind(System.Type)
-IsEnumType(System.Type)
-CheckAndPromoteOperand(System.Type,System.String,System.Linq.Expressions.Expression&,System.Int32)
-CheckAndPromoteOperands(System.Type,System.String,System.Linq.Expressions.Expression&,System.Linq.Expressions.Expression&,System.Int32)
-IncompatibleOperandsError(System.String,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Int32)
-FindPropertyOrField(System.Type,System.String,System.Boolean)
-FindMethod(System.Type,System.String,System.Boolean,System.Linq.Expressions.Expression[],System.Reflection.MethodBase&)
-FindIndexer(System.Type,System.Linq.Expressions.Expression[],System.Reflection.MethodBase&)
-SelfAndBaseTypes(System.Type)
-SelfAndBaseClasses()
-AddInterface(System.Collections.Generic.List`1<System.Type>,System.Type)
-FindBestMethod(System.Collections.Generic.IEnumerable`1<System.Reflection.MethodBase>,System.Linq.Expressions.Expression[],System.Reflection.MethodBase&)
-IsApplicable(System.Linq.Dynamic.Core.ExpressionParser/MethodData,System.Linq.Expressions.Expression[])
-PromoteExpression(System.Linq.Expressions.Expression,System.Type,System.Boolean,System.Boolean)
-ParseNumber(System.String,System.Type)
-ParseEnum(System.String,System.Type)
-IsCompatibleWith(System.Type,System.Type)
-IsBetterThan(System.Linq.Expressions.Expression[],System.Linq.Dynamic.Core.ExpressionParser/MethodData,System.Linq.Dynamic.Core.ExpressionParser/MethodData)
-CompareConversions(System.Type,System.Type,System.Type)
-GenerateEqual(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateNotEqual(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateGreaterThan(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateGreaterThanEqual(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateLessThan(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateLessThanEqual(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateAdd(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateSubtract(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateStringConcat(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GetStaticMethod(System.String,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-GenerateStaticMethodCall(System.String,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)
-OptimizeForEqualityIfPossible(System.Linq.Expressions.Expression&,System.Linq.Expressions.Expression&)
-OptimizeStringForEqualityIfPossible(System.String,System.Type)
-TokenIdentifierIs(System.String)
-GetIdentifier()
-ParseError(System.String,System.Object[])
-ParseError(System.Int32,System.String,System.Object[])
-CreateKeywords()
-ResetDynamicLinqTypes()
+ToNullableType(System.Type)
+TryGetMemberName(System.Linq.Expressions.Expression,System.String&)
+CheckAndPromoteOperand(System.Type,System.String,System.Linq.Expressions.Expression&,System.Int32)
+CheckAndPromoteOperands(System.Type,System.String,System.Linq.Expressions.Expression&,System.Linq.Expressions.Expression&,System.Int32)
+IncompatibleOperandError(System.String,System.Linq.Expressions.Expression,System.Int32)
+IncompatibleOperandsError(System.String,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Int32)
+FindPropertyOrField(System.Type,System.String,System.Boolean)
+TokenIdentifierIs(System.String)
+GetIdentifier()
+ParseError(System.String,System.Object[])
+ParseError(System.Int32,System.String,System.Object[])

diff --git a/report/System.Linq.Dynamic.Core_ExpressionPromoter.htm b/report/System.Linq.Dynamic.Core_ExpressionPromoter.htm new file mode 100644 index 00000000..63c19ca0 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_ExpressionPromoter.htm @@ -0,0 +1,150 @@ + + + + + +System.Linq.Dynamic.Core.Parser.ExpressionPromoter - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.ExpressionPromoter
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionPromoter.cs
Covered lines:48
Uncovered lines:3
Coverable lines:51
Total lines:101
Line coverage:94.1%
Branch coverage:92.8%
+

Metrics

+ + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
Promote(...)201638494.1293.10
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionPromoter.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Linq.Expressions;
 2using System.Reflection;
 3
 4namespace System.Linq.Dynamic.Core.Parser
 5{
 6    internal static class ExpressionPromoter
 7    {
 8        public static Expression Promote(Expression expr, Type type, bool exact, bool convertExpr)
 40979        {
 409710             if (expr.Type == type)
 55311            {
 55312                return expr;
 13            }
 14
 354415            var ce = expr as ConstantExpression;
 16
 354417             if (ce != null)
 84618            {
 84619                 if (ce == Constants.NullLiteral || ce.Value == null)
 5920                {
 5921                     if (!type.GetTypeInfo().IsValueType || TypeHelper.IsNullableType(type))
 3722                    {
 3723                        return Expression.Constant(null, type);
 24                    }
 2225                }
 26                else
 78727                {
 78728                     if (ConstantExpressionHelper.TryGetText(ce, out string text))
 71429                    {
 71430                        Type target = TypeHelper.GetNonNullableType(type);
 71431                        object value = null;
 32
 33#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 34                        switch (Type.GetTypeCode(ce.Type))
 35                        {
 36                            case TypeCode.Int32:
 37                            case TypeCode.UInt32:
 38                            case TypeCode.Int64:
 39                            case TypeCode.UInt64:
 40                                value = TypeHelper.ParseNumber(text, target);
 41
 42                                // Make sure an enum value stays an enum value
 43                                if (target.IsEnum)
 44                                {
 45                                    value = Enum.ToObject(target, value);
 46                                }
 47                                break;
 48
 49                            case TypeCode.Double:
 50                                if (target == typeof(decimal)) value = TypeHelper.ParseNumber(text, target);
 51                                break;
 52
 53                            case TypeCode.String:
 54                                value = TypeHelper.ParseEnum(text, target);
 55                                break;
 56                        }
 57#else
 71458                         if (ce.Type == typeof(Int32) || ce.Type == typeof(UInt32) || ce.Type == typeof(Int64) || ce.Type
 70359                        {
 70360                            value = TypeHelper.ParseNumber(text, target);
 61
 62                            // Make sure an enum value stays an enum value
 70363                             if (target.GetTypeInfo().IsEnum)
 064                            {
 065                                value = Enum.ToObject(target, value);
 066                            }
 70367                        }
 1168                         else if (ce.Type == typeof(Double))
 1069                        {
 1070                             if (target == typeof(decimal))
 471                            {
 472                                value = TypeHelper.ParseNumber(text, target);
 473                            }
 1074                        }
 175                         else if (ce.Type == typeof(String))
 176                        {
 177                            value = TypeHelper.ParseEnum(text, target);
 178                        }
 79#endif
 71480                         if (value != null)
 64481                        {
 64482                            return Expression.Constant(value, type);
 83                        }
 7084                    }
 14385                }
 16586            }
 87
 286388             if (TypeHelper.IsCompatibleWith(expr.Type, type))
 116089            {
 116090                 if (type.GetTypeInfo().IsValueType || exact || expr.Type.GetTypeInfo().IsValueType && convertExpr)
 111491                {
 111492                    return Expression.Convert(expr, type);
 93                }
 94
 4695                return expr;
 96            }
 97
 170398            return null;
 409799        }
 100    }
 101}
+
+
+ +
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_ExtensibilityPoint.htm b/report/System.Linq.Dynamic.Core_ExtensibilityPoint.htm index 974f7cbd..b132d83a 100644 --- a/report/System.Linq.Dynamic.Core_ExtensibilityPoint.htm +++ b/report/System.Linq.Dynamic.Core_ExtensibilityPoint.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.ExtensibilityPoint Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ExtensibilityPoint.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ExtensibilityPoint.cs Covered lines:1 Uncovered lines:0 Coverable lines:1 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ExtensibilityPoint.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ExtensibilityPoint.cs

@@ -49,12 +49,12 @@

- +
#LineLine coverage
 12        /// Place to optimize your queries. Example: Add a reference to Nuget package Linq.Expression.Optimizer
 13        /// and in your program initializers set Extensibility.QueryOptimizer = ExpressionOptimizer.visit;
 14        /// </summary>
 2115        public static Func<Expression, Expression> QueryOptimizer = e => e;
 14815        public static Func<Expression, Expression> QueryOptimizer = e => e;
 16    }
 17}
- +

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_GroupResult.htm b/report/System.Linq.Dynamic.Core_GroupResult.htm index 907b659c..17084b9c 100644 --- a/report/System.Linq.Dynamic.Core_GroupResult.htm +++ b/report/System.Linq.Dynamic.Core_GroupResult.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.GroupResult Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\GroupResult.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\GroupResult.cs Covered lines:7 Uncovered lines:0 Coverable lines:7 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\GroupResult.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\GroupResult.cs

@@ -84,7 +84,7 @@

#LineLine coverage
 47}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_KeywordsHelper.htm b/report/System.Linq.Dynamic.Core_KeywordsHelper.htm new file mode 100644 index 00000000..a412407f --- /dev/null +++ b/report/System.Linq.Dynamic.Core_KeywordsHelper.htm @@ -0,0 +1,118 @@ + + + + + +System.Linq.Dynamic.Core.Parser.KeywordsHelper - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.KeywordsHelper
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\KeywordsHelper.cs
Covered lines:41
Uncovered lines:0
Coverable lines:41
Total lines:67
Line coverage:100%
Branch coverage:75%
+

Metrics

+ + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.ctor(...)10410080
TryGetValue(...)10100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\KeywordsHelper.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Collections.Generic;
 2
 3namespace System.Linq.Dynamic.Core.Parser
 4{
 5    internal class KeywordsHelper
 6    {
 7        public const string SYMBOL_IT = "$";
 8        public const string SYMBOL_PARENT = "^";
 9        public const string SYMBOL_ROOT = "~";
 10
 11        public const string KEYWORD_IT = "it";
 12        public const string KEYWORD_PARENT = "parent";
 13        public const string KEYWORD_ROOT = "root";
 14        public const string KEYWORD_IIF = "iif";
 15        public const string KEYWORD_NEW = "new";
 16        public const string KEYWORD_ISNULL = "isnull";
 17
 49218        private readonly IDictionary<string, object> _keywords = new Dictionary<string, object>(StringComparer.OrdinalIg
 49219        {
 49220            { "true", Constants.TrueLiteral },
 49221            { "false", Constants.FalseLiteral },
 49222            { "null", Constants.NullLiteral }
 49223        };
 24
 49225        public KeywordsHelper(ParsingConfig config)
 49226        {
 49227             if (config.AreContextKeywordsEnabled)
 49228            {
 49229                _keywords.Add(KEYWORD_IT, KEYWORD_IT);
 49230                _keywords.Add(KEYWORD_PARENT, KEYWORD_PARENT);
 49231                _keywords.Add(KEYWORD_ROOT, KEYWORD_ROOT);
 49232            }
 33
 49234            _keywords.Add(SYMBOL_IT, SYMBOL_IT);
 49235            _keywords.Add(SYMBOL_PARENT, SYMBOL_PARENT);
 49236            _keywords.Add(SYMBOL_ROOT, SYMBOL_ROOT);
 49237            _keywords.Add(KEYWORD_IIF, KEYWORD_IIF);
 49238            _keywords.Add(KEYWORD_NEW, KEYWORD_NEW);
 49239            _keywords.Add(KEYWORD_ISNULL, KEYWORD_ISNULL);
 40
 4477241            foreach (Type type in PredefinedTypesHelper.PredefinedTypes.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key)
 1082442            {
 1082443                _keywords[type.FullName] = type;
 1082444                _keywords[type.Name] = type;
 1082445            }
 46
 934847            foreach (KeyValuePair<string, Type> pair in PredefinedTypesHelper.PredefinedTypesShorthands)
 393648            {
 393649                _keywords.Add(pair.Key, pair.Value);
 393650            }
 51
 49252             if (config.CustomTypeProvider != null)
 3653            {
 32254                foreach (Type type in config.CustomTypeProvider.GetCustomTypes())
 10755                {
 10756                    _keywords[type.FullName] = type;
 10757                    _keywords[type.Name] = type;
 10758                }
 3659            }
 49260        }
 61
 62        public bool TryGetValue(string name, out object type)
 90463        {
 90464            return _keywords.TryGetValue(name, out type);
 90465        }
 66    }
 67}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_LinqProviderExtensions.htm b/report/System.Linq.Dynamic.Core_LinqProviderExtensions.htm index d4e22028..1c06245a 100644 --- a/report/System.Linq.Dynamic.Core_LinqProviderExtensions.htm +++ b/report/System.Linq.Dynamic.Core_LinqProviderExtensions.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.Extensions.LinqProviderExtensions Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs Covered lines:19 Uncovered lines:3 Coverable lines:22 @@ -33,7 +33,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Extensions\LinqProviderExtensions.cs

@@ -51,22 +51,22 @@

- - - + + + - - + + - - + + - + - + @@ -84,13 +84,13 @@

- - + +
#LineLine coverage
 12        /// <param name="source">The IQueryable</param>
 13        /// <returns>true if provider is LinqToObjects, else false</returns>
 14        public static bool IsLinqToObjects([NotNull] this IQueryable source)
 31515        {
 31516            Check.NotNull(source, nameof(source));
 31517            Check.NotNull(source.Provider, nameof(source.Provider));
 40315        {
 40316            Check.NotNull(source, nameof(source));
 40317            Check.NotNull(source.Provider, nameof(source.Provider));
 18
 31519            return IsProviderEnumerableQuery(source.Provider);
 31520        }
 40319            return IsProviderEnumerableQuery(source.Provider);
 40320        }
 21
 22        private static bool IsProviderEnumerableQuery(IQueryProvider provider)
 31623        {
 31624            Type baseType = provider.GetType().GetTypeInfo().BaseType;
 40423        {
 40424            Type baseType = provider.GetType().GetTypeInfo().BaseType;
 25#if NET35
 26            bool isLinqToObjects = baseType.FullName.Contains("EnumerableQuery");
 27#else
 31628            bool isLinqToObjects = baseType == typeof(EnumerableQuery);
 40428            bool isLinqToObjects = baseType == typeof(EnumerableQuery);
 29#endif
 31630             if (!isLinqToObjects)
 40430             if (!isLinqToObjects)
 3431            {
 32                // add support for https://github.com/StefH/QueryInterceptor.Core, version 1.0.1 and up
 3433                 if (baseType.Name == "QueryTranslatorProvider")
 45                }
 3346            }
 47
 31548            return isLinqToObjects;
 31649        }
 40348            return isLinqToObjects;
 40449        }
 50    }
 51}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_MethodData.htm b/report/System.Linq.Dynamic.Core_MethodData.htm new file mode 100644 index 00000000..16fe2795 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_MethodData.htm @@ -0,0 +1,58 @@ + + + + + +System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodData - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodData
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\SupportedMethods\MethodData.cs
Covered lines:3
Uncovered lines:0
Coverable lines:3
Total lines:12
Line coverage:100%
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\SupportedMethods\MethodData.cs

+ + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Linq.Expressions;
 2using System.Reflection;
 3
 4namespace System.Linq.Dynamic.Core.Parser.SupportedMethods
 5{
 6    internal class MethodData
 7    {
 70718        public MethodBase MethodBase { get; set; }
 142989        public ParameterInfo[] Parameters { get; set; }
 156210        public Expression[] Args { get; set; }
 11    }
 12}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_MethodFinder.htm b/report/System.Linq.Dynamic.Core_MethodFinder.htm new file mode 100644 index 00000000..ba45720b --- /dev/null +++ b/report/System.Linq.Dynamic.Core_MethodFinder.htm @@ -0,0 +1,296 @@ + + + + + +System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodFinder - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodFinder
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\SupportedMethods\MethodFinder.cs
Covered lines:142
Uncovered lines:6
Coverable lines:148
Total lines:229
Line coverage:95.9%
Branch coverage:91%
+

Metrics

+ + + + + + + + + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
ContainsMethod(...)10100100
FindMethod(...)52100100
FindBestMethod(...)1016100100
FindIndexer(...)6478.9560
IsApplicable(...)51690.9188.89
IsBetterThan(...)51610088.89
CompareConversions(...)12512100100
SelfAndBaseTypes(...)22100100
AddInterface(...)32100100
SelfAndBaseClasses()4210066.67
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\SupportedMethods\MethodFinder.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Collections.Generic;
 2using System.Linq.Expressions;
 3using System.Reflection;
 4
 5namespace System.Linq.Dynamic.Core.Parser.SupportedMethods
 6{
 7    internal static class MethodFinder
 8    {
 9        public static bool ContainsMethod(Type type, string methodName, bool staticAccess, Expression[] args)
 24610        {
 24611            return FindMethod(type, methodName, staticAccess, args, out var _) == 1;
 24612        }
 13
 14        public static int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase 
 26415        {
 16#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 17            BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | (staticAccess ? BindingFlags.Static :
 18            foreach (Type t in SelfAndBaseTypes(type))
 19            {
 20                MemberInfo[] members = t.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, methodName);
 21                int count = FindBestMethod(members.Cast<MethodBase>(), args, out method);
 22                if (count != 0)
 23                {
 24                    return count;
 25                }
 26            }
 27#else
 128728            foreach (Type t in SelfAndBaseTypes(type))
 37729            {
 983030                 MethodInfo[] methods = t.GetTypeInfo().DeclaredMethods.Where(x => (x.IsStatic || !staticAccess) && x.Nam
 37731                int count = FindBestMethod(methods, args, out method);
 37732                 if (count != 0)
 25933                {
 25934                    return count;
 35                }
 11836            }
 37#endif
 538            method = null;
 539            return 0;
 26440        }
 41
 42        public static int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method)
 38543        {
 38544            MethodData[] applicable = methods.
 329145                Select(m => new MethodData { MethodBase = m, Parameters = m.GetParameters() }).
 329146                Where(m => IsApplicable(m, args)).
 38547                ToArray();
 48
 38549             if (applicable.Length > 1)
 14550            {
 364751                applicable = applicable.Where(m => applicable.All(n => m == n || IsBetterThan(args, m, n))).ToArray();
 14552            }
 53
 38554             if (args.Length == 2 && applicable.Length > 1 && (args[0].Type == typeof(Guid?) || args[1].Type == typeof(Gu
 455            {
 456                applicable = applicable.Take(1).ToArray();
 457            }
 58
 38559             if (applicable.Length == 1)
 26160            {
 26161                MethodData md = applicable[0];
 127462                 for (int i = 0; i < args.Length; i++)
 37663                {
 37664                    args[i] = md.Args[i];
 37665                }
 26166                method = md.MethodBase;
 26167            }
 68            else
 12469            {
 12470                method = null;
 12471            }
 72
 38573            return applicable.Length;
 38574        }
 75
 76        public static int FindIndexer(Type type, Expression[] args, out MethodBase method)
 177        {
 478            foreach (Type t in SelfAndBaseTypes(type))
 179            {
 180                MemberInfo[] members = t.GetDefaultMembers();
 181                 if (members.Length != 0)
 182                {
 183                    IEnumerable<MethodBase> methods = members.OfType<PropertyInfo>().
 184#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 185                        Select(p => (MethodBase)p.GetGetMethod()).
 186                        Where(m => m != null);
 187#else
 388                    Select(p => (MethodBase)p.GetMethod);
 89#endif
 190                    int count = FindBestMethod(methods, args, out method);
 191                     if (count != 0)
 192                    {
 193                        return count;
 94                    }
 095                }
 096            }
 97
 098            method = null;
 099            return 0;
 1100        }
 101
 102        static bool IsApplicable(MethodData method, Expression[] args)
 2906103        {
 2906104             if (method.Parameters.Length != args.Length)
 45105            {
 45106                return false;
 107            }
 108
 2861109            Expression[] promotedArgs = new Expression[args.Length];
 10180110             for (int i = 0; i < args.Length; i++)
 3904111            {
 3904112                ParameterInfo pi = method.Parameters[i];
 3904113                 if (pi.IsOut)
 0114                {
 0115                    return false;
 116                }
 117
 3904118                Expression promoted = ExpressionPromoter.Promote(args[i], pi.ParameterType, false, method.MethodBase.Dec
 3904119                 if (promoted == null)
 1675120                {
 1675121                    return false;
 122                }
 2229123                promotedArgs[i] = promoted;
 2229124            }
 1186125            method.Args = promotedArgs;
 1186126            return true;
 2906127        }
 128
 129        static bool IsBetterThan(Expression[] args, MethodData first, MethodData second)
 2219130        {
 2219131            bool better = false;
 5012132             for (int i = 0; i < args.Length; i++)
 2291133            {
 2291134                CompareConversionType result = CompareConversions(args[i].Type, first.Parameters[i].ParameterType, secon
 135
 136                // If second is better, return false
 2291137                 if (result == CompareConversionType.Second)
 921138                {
 921139                    return false;
 140                }
 141
 142                // If first is better, return true
 1370143                 if (result == CompareConversionType.First)
 1083144                {
 1083145                    return true;
 146                }
 147
 148                // If both are same, just set better to true and continue
 287149                 if (result == CompareConversionType.Both)
 287150                {
 287151                    better = true;
 287152                }
 287153            }
 154
 215155            return better;
 2219156        }
 157
 158        // Return "First" if s -> t1 is a better conversion than s -> t2
 159        // Return "Second" if s -> t2 is a better conversion than s -> t1
 160        // Return "Both" if neither conversion is better
 161        static CompareConversionType CompareConversions(Type source, Type first, Type second)
 2291162        {
 2291163             if (first == second)
 72164            {
 72165                return CompareConversionType.Both;
 166            }
 2219167             if (source == first)
 646168            {
 646169                return CompareConversionType.First;
 170            }
 1573171             if (source == second)
 601172            {
 601173                return CompareConversionType.Second;
 174            }
 175
 972176            bool firstIsCompatibleWithSecond = TypeHelper.IsCompatibleWith(first, second);
 972177            bool secondIsCompatibleWithFirst = TypeHelper.IsCompatibleWith(second, first);
 178
 972179             if (firstIsCompatibleWithSecond && !secondIsCompatibleWithFirst)
 357180            {
 357181                return CompareConversionType.First;
 182            }
 615183             if (secondIsCompatibleWithFirst && !firstIsCompatibleWithSecond)
 240184            {
 240185                return CompareConversionType.Second;
 186            }
 187
 375188             if (TypeHelper.IsSignedIntegralType(first) && TypeHelper.IsUnsignedIntegralType(second))
 80189            {
 80190                return CompareConversionType.First;
 191            }
 295192             if (TypeHelper.IsSignedIntegralType(second) && TypeHelper.IsUnsignedIntegralType(first))
 80193            {
 80194                return CompareConversionType.Second;
 195            }
 196
 215197            return CompareConversionType.Both;
 2291198        }
 199
 200        static IEnumerable<Type> SelfAndBaseTypes(Type type)
 265201        {
 265202             if (type.GetTypeInfo().IsInterface)
 249203            {
 249204                var types = new List<Type>();
 249205                AddInterface(types, type);
 249206                return types;
 207            }
 16208            return SelfAndBaseClasses(type);
 265209        }
 210
 211        static IEnumerable<Type> SelfAndBaseClasses(Type type)
 16212        {
 17213             while (type != null)
 17214            {
 17215                yield return type;
 1216                type = type.GetTypeInfo().BaseType;
 1217            }
 218        }
 219
 220        static void AddInterface(List<Type> types, Type type)
 439221        {
 439222             if (!types.Contains(type))
 381223            {
 381224                types.Add(type);
 1713225                foreach (Type t in type.GetInterfaces()) AddInterface(types, t);
 381226            }
 439227        }
 228    }
 229}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_PagedResult.htm b/report/System.Linq.Dynamic.Core_PagedResult.htm index d2f3d2cb..ef75723e 100644 --- a/report/System.Linq.Dynamic.Core_PagedResult.htm +++ b/report/System.Linq.Dynamic.Core_PagedResult.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.PagedResult Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs Covered lines:5 Uncovered lines:0 Coverable lines:5 @@ -24,7 +24,7 @@

Summary

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs

@@ -94,7 +94,7 @@

#LineLine coverage
 64}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_PagedResult_1.htm b/report/System.Linq.Dynamic.Core_PagedResult_1.htm index 52003c08..6e2546df 100644 --- a/report/System.Linq.Dynamic.Core_PagedResult_1.htm +++ b/report/System.Linq.Dynamic.Core_PagedResult_1.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.PagedResult`1 Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs Covered lines:1 Uncovered lines:0 Coverable lines:1 @@ -24,7 +24,7 @@

Summary

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\PagedResult.cs

@@ -94,7 +94,7 @@

#LineLine coverage
 64}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_ParameterExpressionHelper.htm b/report/System.Linq.Dynamic.Core_ParameterExpressionHelper.htm new file mode 100644 index 00000000..57f950ef --- /dev/null +++ b/report/System.Linq.Dynamic.Core_ParameterExpressionHelper.htm @@ -0,0 +1,60 @@ + + + + + +System.Linq.Dynamic.Core.ParameterExpressionHelper - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.ParameterExpressionHelper
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ParameterExpressionHelper.cs
Covered lines:3
Uncovered lines:0
Coverable lines:3
Total lines:12
Line coverage:100%
+

Metrics

+ + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
CreateParameterExpression(...)10100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ParameterExpressionHelper.cs

+ + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Linq.Expressions;
 2
 3namespace System.Linq.Dynamic.Core
 4{
 5    internal static class ParameterExpressionHelper
 6    {
 7        public static ParameterExpression CreateParameterExpression(Type type, string name)
 5758        {
 5759            return Expression.Parameter(type, name);
 57510        }
 11    }
 12}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_ParseException.htm b/report/System.Linq.Dynamic.Core_ParseException.htm index b541afc6..2b7e059d 100644 --- a/report/System.Linq.Dynamic.Core_ParseException.htm +++ b/report/System.Linq.Dynamic.Core_ParseException.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.Exceptions.ParseException Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Exceptions\ParseException.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Exceptions\ParseException.cs Covered lines:4 Uncovered lines:4 Coverable lines:8 @@ -32,7 +32,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Exceptions\ParseException.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Exceptions\ParseException.cs

@@ -47,7 +47,7 @@

- + @@ -58,10 +58,10 @@

- - - - + + + + @@ -77,7 +77,7 @@

- + @@ -104,7 +104,7 @@

#LineLine coverage
 9    /// <summary>
 10    /// Represents errors that occur while parsing dynamic linq string expressions.
 11    /// </summary>
 12#if !(SILVERLIGHT || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD || PORTABLE || WPSL)
 12#if !(SILVERLIGHT || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD || PORTABLE || WPSL || NETSTANDARD2_0)
 13    [Serializable]
 14#endif
 15    public sealed class ParseException : Exception
 20        /// <param name="message">The message that describes the error.</param>
 21        /// <param name="position">The location in the parsed string that produced the <see cref="ParseException"/></par
 22        public ParseException(string message, int position)
 3923            : base(message)
 3924        {
 3925            Position = position;
 3926        }
 4023            : base(message)
 4024        {
 4025            Position = position;
 4026        }
 27
 28        /// <summary>
 29        /// The location in the parsed string that produced the <see cref="ParseException"/>.
 039            return string.Format(CultureInfo.CurrentCulture, Res.ParseExceptionFormat, Message, Position);
 040        }
 41
 42#if !(SILVERLIGHT || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD || PORTABLE || WPSL)
 42#if !(SILVERLIGHT || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD || PORTABLE || WPSL || NETSTANDARD2_0)
 43        ParseException(SerializationInfo info, StreamingContext context)
 44            : base(info, context)
 45        {
 66}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_ParsingConfig.htm b/report/System.Linq.Dynamic.Core_ParsingConfig.htm new file mode 100644 index 00000000..41868036 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_ParsingConfig.htm @@ -0,0 +1,110 @@ + + + + + +System.Linq.Dynamic.Core.ParsingConfig - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.ParsingConfig
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ParsingConfig.cs
Covered lines:12
Uncovered lines:0
Coverable lines:12
Total lines:52
Line coverage:100%
Branch coverage:50%
+

Metrics

+ + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.ctor()10100100
.cctor()10100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\ParsingConfig.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Linq.Dynamic.Core.CustomTypeProviders;
 2
 3namespace System.Linq.Dynamic.Core
 4{
 5    /// <summary>
 6    /// Configuration class for Dynamic Linq.
 7    /// </summary>
 8    public class ParsingConfig
 9    {
 45710        internal static ParsingConfig Default { get; } = new ParsingConfig();
 11
 12        private IDynamicLinkCustomTypeProvider _customTypeProvider;
 13
 14        /// <summary>
 15        /// Gets or sets the <see cref="IDynamicLinkCustomTypeProvider"/>.
 16        /// </summary>
 17        public IDynamicLinkCustomTypeProvider CustomTypeProvider
 18        {
 19            get
 54020            {
 21#if !(DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
 22                // only use DefaultDynamicLinqCustomTypeProvider if not WINDOWS_APP || UAP10_0 || NETSTANDARD
 23                return _customTypeProvider ?? (_customTypeProvider = new DefaultDynamicLinqCustomTypeProvider());
 24#else
 54025                return _customTypeProvider;
 26#endif
 54027            }
 28
 29            set
 630            {
 631                 if (_customTypeProvider != value)
 632                {
 633                    _customTypeProvider = value;
 634                }
 635            }
 36        }
 37
 38        /// <summary>
 39        /// Determines if the context keywords (it, parent, and root) are valid and usable inside a Dynamic Linq string 
 40        /// Does not affect the usability of the equivalent context symbols ($, ^ and ~).
 41        /// </summary>
 50042        public bool AreContextKeywordsEnabled { get; set; } = true;
 43
 44        /// <summary>
 45        /// Gets or sets a value indicating whether to use dynamic object class for anonymous types.
 46        /// </summary>
 47        /// <value>
 48        /// <c>true</c> if wether to use dynamic object class for anonymous types; otherwise, <c>false</c>.
 49        /// </value>
 4350        public bool UseDynamicObjectClassForAnonymousTypes { get; set; }
 51    }
 52}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_PredefinedTypesHelper.htm b/report/System.Linq.Dynamic.Core_PredefinedTypesHelper.htm new file mode 100644 index 00000000..7d33da8f --- /dev/null +++ b/report/System.Linq.Dynamic.Core_PredefinedTypesHelper.htm @@ -0,0 +1,152 @@ + + + + + +System.Linq.Dynamic.Core.Parser.PredefinedTypesHelper - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.PredefinedTypesHelper
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\PredefinedTypesHelper.cs
Covered lines:45
Uncovered lines:12
Coverable lines:57
Total lines:99
Line coverage:78.9%
Branch coverage:50%
+

Metrics

+ + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
.cctor()10100100
TryAdd(...)2200
IsPredefinedType(...)32100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\PredefinedTypesHelper.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Collections.Concurrent;
 2using System.Collections.Generic;
 3using System.Linq.Dynamic.Core.Validation;
 4
 5namespace System.Linq.Dynamic.Core.Parser
 6{
 7    internal static class PredefinedTypesHelper
 8    {
 9        // These shorthands have different name than actual type and therefore not recognized by default from the Predef
 110        public static readonly IDictionary<string, Type> PredefinedTypesShorthands = new Dictionary<string, Type>
 111        {
 112            { "int", typeof(int) },
 113            { "uint", typeof(uint) },
 114            { "short", typeof(short) },
 115            { "ushort", typeof(ushort) },
 116            { "long", typeof(long) },
 117            { "ulong", typeof(ulong) },
 118            { "bool", typeof(bool) },
 119            { "float", typeof(float) }
 120        };
 21
 122        public static readonly IDictionary<Type, int> PredefinedTypes = new ConcurrentDictionary<Type, int>(new Dictiona
 123            { typeof(object), 0 },
 124            { typeof(bool), 0 },
 125            { typeof(char), 0 },
 126            { typeof(string), 0 },
 127            { typeof(sbyte), 0 },
 128            { typeof(byte), 0 },
 129            { typeof(short), 0 },
 130            { typeof(ushort), 0 },
 131            { typeof(int), 0 },
 132            { typeof(uint), 0 },
 133            { typeof(long), 0 },
 134            { typeof(ulong), 0 },
 135            { typeof(float), 0 },
 136            { typeof(double), 0 },
 137            { typeof(decimal), 0 },
 138            { typeof(DateTime), 0 },
 139            { typeof(DateTimeOffset), 0 },
 140            { typeof(TimeSpan), 0 },
 141            { typeof(Guid), 0 },
 142            { typeof(Math), 0 },
 143            { typeof(Convert), 0 },
 144            { typeof(Uri), 0 }
 145        });
 46
 47        static PredefinedTypesHelper()
 148        {
 49#if !(NET35 || SILVERLIGHT || NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 50            //System.Data.Entity is always here, so overwrite short name of it with EntityFramework if EntityFramework i
 51            //EF5(or 4.x??), System.Data.Objects.DataClasses.EdmFunctionAttribute
 52            //There is also an System.Data.Entity, Version=3.5.0.0, but no Functions.
 53            TryAdd("System.Data.Objects.EntityFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKey
 54            TryAdd("System.Data.Objects.SqlClient.SqlFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neutral, Pu
 55            TryAdd("System.Data.Objects.SqlClient.SqlSpatialFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neut
 56
 57            //EF6,System.Data.Entity.DbFunctionAttribute
 58            TryAdd("System.Data.Entity.Core.Objects.EntityFunctions, EntityFramework, Version=6.0.0.0, Culture=neutral, 
 59            TryAdd("System.Data.Entity.DbFunctions, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b7
 60            TryAdd("System.Data.Entity.Spatial.DbGeography, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKey
 61            TryAdd("System.Data.Entity.SqlServer.SqlFunctions, EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutr
 62            TryAdd("System.Data.Entity.SqlServer.SqlSpatialFunctions, EntityFramework.SqlServer, Version=6.0.0.0, Cultur
 63#endif
 64
 65#if NETSTANDARD2_0
 66            TryAdd("Microsoft.EntityFrameworkCore.DynamicLinq.DynamicFunctions, Microsoft.EntityFrameworkCore.DynamicLin
 67#endif
 168        }
 69
 70        private static void TryAdd(string typeName, int x)
 071        {
 72            try
 073            {
 074                Type efType = Type.GetType(typeName);
 075                 if (efType != null)
 076                {
 077                    PredefinedTypes.Add(efType, x);
 078                }
 079            }
 080            catch
 081            {
 82                // in case of exception, do not add
 083            }
 084        }
 85
 86        public static bool IsPredefinedType(ParsingConfig config, Type type)
 2687        {
 2688            Check.NotNull(config, nameof(config));
 2689            Check.NotNull(type, nameof(type));
 90
 2691             if (PredefinedTypes.ContainsKey(type))
 1492            {
 1493                return true;
 94            }
 95
 1296            return config.CustomTypeProvider != null && config.CustomTypeProvider.GetCustomTypes().Contains(type);
 2697        }
 98    }
 99}
+
+
+ + \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_Res.htm b/report/System.Linq.Dynamic.Core_Res.htm index 58bf1a2a..b0be392e 100644 --- a/report/System.Linq.Dynamic.Core_Res.htm +++ b/report/System.Linq.Dynamic.Core_Res.htm @@ -25,6 +25,6 @@

Summary

File(s)

No files found. This usually happens if a file isn't covered by a test or the class does not contain any sequence points (e.g. a class that only contains auto properties).

-
+ \ No newline at end of file diff --git a/report/System.Linq.Dynamic.Core_TextParser.htm b/report/System.Linq.Dynamic.Core_TextParser.htm index 927ce00d..9e5967d3 100644 --- a/report/System.Linq.Dynamic.Core_TextParser.htm +++ b/report/System.Linq.Dynamic.Core_TextParser.htm @@ -15,13 +15,13 @@

Summary

Class:System.Linq.Dynamic.Core.Tokenizer.TextParser Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\TextParser.cs -Covered lines:287 -Uncovered lines:1 -Coverable lines:288 -Total lines:423 -Line coverage:99.6% -Branch coverage:93.9% +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\TextParser.cs +Covered lines:303 +Uncovered lines:3 +Coverable lines:306 +Total lines:447 +Line coverage:99% +Branch coverage:94.1%

Metrics

@@ -31,9 +31,9 @@

Metrics

.ctor(...)10100100 SetTextPos(...)3210066.67 NextChar()4410080 -NextToken()74409610096.40 +NextToken()771638410096.52 ValidateToken(...)22100100 -ValidateToken(...)227566.67 +ValidateToken(...)226066.67 ValidateExpression()22100100 ValidateDigit()22100100 ValidateHexChar()22100100 @@ -45,7 +45,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\TextParser.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\TextParser.cs

@@ -83,398 +83,422 @@

- - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 32        private char _ch;
 33        public Token CurrentToken;
 34
 38935        public TextParser(string text)
 38936        {
 38937            _text = text;
 38938            _textLen = _text.Length;
 38939            SetTextPos(0);
 38940            NextToken();
 38641        }
 51035        public TextParser(string text)
 51036        {
 51037            _text = text;
 51038            _textLen = _text.Length;
 51039            SetTextPos(0);
 51040            NextToken();
 50741        }
 42
 43        private void SetTextPos(int pos)
 38944        {
 38945            _textPos = pos;
 38946             _ch = _textPos < _textLen ? _text[_textPos] : '\0';
 38947        }
 51044        {
 51045            _textPos = pos;
 51046             _ch = _textPos < _textLen ? _text[_textPos] : '\0';
 51047        }
 48
 49        private void NextChar()
 644150        {
 1288251             if (_textPos < _textLen) _textPos++;
 644152             _ch = _textPos < _textLen ? _text[_textPos] : '\0';
 644153        }
 898150        {
 1796251             if (_textPos < _textLen) _textPos++;
 898152             _ch = _textPos < _textLen ? _text[_textPos] : '\0';
 898153        }
 54
 55        public void NextToken()
 234756        {
 317057             while (char.IsWhiteSpace(_ch))
 82358                NextChar();
 59
 234760            TokenId tokenId = TokenId.Unknown;
 234761            int tokenPos = _textPos;
 62
 234763             switch (_ch)
 64            {
 65                case '!':
 866                    NextChar();
 867                     if (_ch == '=')
 768                    {
 769                        NextChar();
 770                        tokenId = TokenId.ExclamationEqual;
 771                    }
 72                    else
 173                    {
 174                        tokenId = TokenId.Exclamation;
 175                    }
 876                    break;
 77
 78                case '%':
 179                    NextChar();
 180                    tokenId = TokenId.Percent;
 181                    break;
 82
 83                case '&':
 1184                    NextChar();
 1185                     if (_ch == '&')
 486                    {
 487                        NextChar();
 488                        tokenId = TokenId.DoubleAmphersand;
 489                    }
 90                    else
 791                    {
 792                        tokenId = TokenId.Amphersand;
 793                    }
 1194                    break;
 95
 96                case '(':
 14697                    NextChar();
 14698                    tokenId = TokenId.OpenParen;
 14699                    break;
 100
 101                case ')':
 140102                    NextChar();
 140103                    tokenId = TokenId.CloseParen;
 140104                    break;
 105
 106                case '{':
 9107                    NextChar();
 9108                    tokenId = TokenId.OpenCurlyParen;
 9109                    break;
 110
 111                case '}':
 8112                    NextChar();
 8113                    tokenId = TokenId.CloseCurlyParen;
 8114                    break;
 115
 116                case '*':
 15117                    NextChar();
 15118                    tokenId = TokenId.Asterisk;
 15119                    break;
 120                case '+':
 16121                    NextChar();
 16122                    tokenId = TokenId.Plus;
 16123                    break;
 124
 125                case ',':
 83126                    NextChar();
 83127                    tokenId = TokenId.Comma;
 83128                    break;
 129
 130                case '-':
 22131                    NextChar();
 22132                    tokenId = TokenId.Minus;
 22133                    break;
 134
 135                case '.':
 139136                    NextChar();
 139137                    tokenId = TokenId.Dot;
 139138                    break;
 139
 140                case '/':
 1141                    NextChar();
 1142                    tokenId = TokenId.Slash;
 1143                    break;
 144
 145                case ':':
 2146                    NextChar();
 2147                    tokenId = TokenId.Colon;
 2148                    break;
 149
 150                case '<':
 39151                    NextChar();
 39152                     if (_ch == '=')
 4153                    {
 4154                        NextChar();
 4155                        tokenId = TokenId.LessThanEqual;
 4156                    }
 35157                     else if (_ch == '>')
 1158                    {
 1159                        NextChar();
 1160                        tokenId = TokenId.LessGreater;
 1161                    }
 34162                     else if (_ch == '<')
 24163                    {
 24164                        NextChar();
 24165                        tokenId = TokenId.DoubleLessThan;
 24166                    }
 167                    else
 10168                    {
 10169                        tokenId = TokenId.LessThan;
 10170                    }
 39171                    break;
 172
 173                case '=':
 122174                    NextChar();
 122175                     if (_ch == '=')
 47176                    {
 47177                        NextChar();
 47178                        tokenId = TokenId.DoubleEqual;
 47179                    }
 75180                     else if (_ch == '>')
 6181                    {
 6182                        NextChar();
 6183                        tokenId = TokenId.Lambda;
 6184                    }
 185                    else
 69186                    {
 69187                        tokenId = TokenId.Equal;
 69188                    }
 122189                    break;
 190
 191                case '>':
 50192                    NextChar();
 50193                     if (_ch == '=')
 4194                    {
 4195                        NextChar();
 4196                        tokenId = TokenId.GreaterThanEqual;
 4197                    }
 46198                     else if (_ch == '>')
 8199                    {
 8200                        NextChar();
 8201                        tokenId = TokenId.DoubleGreaterThan;
 8202                    }
 203                    else
 38204                    {
 38205                        tokenId = TokenId.GreaterThan;
 38206                    }
 50207                    break;
 208
 209                case '?':
 12210                    NextChar();
 12211                     if (_ch == '?')
 6212                    {
 6213                        NextChar();
 6214                        tokenId = TokenId.NullCoalescing;
 6215                    }
 216                    else
 6217                    {
 6218                        tokenId = TokenId.Question;
 6219                    }
 12220                    break;
 221
 222                case '[':
 8223                    NextChar();
 8224                    tokenId = TokenId.OpenBracket;
 8225                    break;
 226
 227                case ']':
 8228                    NextChar();
 8229                    tokenId = TokenId.CloseBracket;
 8230                    break;
 231
 232                case '|':
 2233                    NextChar();
 2234                     if (_ch == '|')
 1235                    {
 1236                        NextChar();
 1237                        tokenId = TokenId.DoubleBar;
 1238                    }
 239                    else
 1240                    {
 1241                        tokenId = TokenId.Bar;
 1242                    }
 2243                    break;
 244
 245                case '"':
 246                case '\'':
 29247                    char quote = _ch;
 248                    do
 29249                    {
 250                        bool escaped;
 251
 252                        do
 230253                        {
 230254                            escaped = false;
 230255                            NextChar();
 256
 230257                             if (_ch == '\\')
 8258                            {
 8259                                escaped = true;
 16260                                 if (_textPos < _textLen) NextChar();
 8261                            }
 230262                        }
 230263                         while (_textPos < _textLen && (_ch != quote || escaped));
 338356        {
 455957             while (char.IsWhiteSpace(_ch))
 117658            {
 117659                NextChar();
 117660            }
 61
 338362            TokenId tokenId = TokenId.Unknown;
 338363            int tokenPos = _textPos;
 64
 338365             switch (_ch)
 66            {
 67                case '!':
 968                    NextChar();
 969                     if (_ch == '=')
 870                    {
 871                        NextChar();
 872                        tokenId = TokenId.ExclamationEqual;
 873                    }
 74                    else
 175                    {
 176                        tokenId = TokenId.Exclamation;
 177                    }
 978                    break;
 79
 80                case '%':
 281                    NextChar();
 282                    tokenId = TokenId.Percent;
 283                    break;
 84
 85                case '&':
 3086                    NextChar();
 3087                     if (_ch == '&')
 488                    {
 489                        NextChar();
 490                        tokenId = TokenId.DoubleAmphersand;
 491                    }
 92                    else
 2693                    {
 2694                        tokenId = TokenId.Amphersand;
 2695                    }
 3096                    break;
 97
 98                case '(':
 22199                    NextChar();
 221100                    tokenId = TokenId.OpenParen;
 221101                    break;
 102
 103                case ')':
 216104                    NextChar();
 216105                    tokenId = TokenId.CloseParen;
 216106                    break;
 107
 108                case '{':
 12109                    NextChar();
 12110                    tokenId = TokenId.OpenCurlyParen;
 12111                    break;
 112
 113                case '}':
 11114                    NextChar();
 11115                    tokenId = TokenId.CloseCurlyParen;
 11116                    break;
 117
 118                case '*':
 16119                    NextChar();
 16120                    tokenId = TokenId.Asterisk;
 16121                    break;
 122
 123                case '+':
 24124                    NextChar();
 24125                    tokenId = TokenId.Plus;
 24126                    break;
 127
 128                case ',':
 104129                    NextChar();
 104130                    tokenId = TokenId.Comma;
 104131                    break;
 132
 133                case '-':
 27134                    NextChar();
 27135                    tokenId = TokenId.Minus;
 27136                    break;
 137
 138                case '.':
 257139                    NextChar();
 257140                    tokenId = TokenId.Dot;
 257141                    break;
 142
 143                case '/':
 2144                    NextChar();
 2145                    tokenId = TokenId.Slash;
 2146                    break;
 147
 148                case ':':
 2149                    NextChar();
 2150                    tokenId = TokenId.Colon;
 2151                    break;
 152
 153                case '<':
 44154                    NextChar();
 44155                     if (_ch == '=')
 4156                    {
 4157                        NextChar();
 4158                        tokenId = TokenId.LessThanEqual;
 4159                    }
 40160                     else if (_ch == '>')
 1161                    {
 1162                        NextChar();
 1163                        tokenId = TokenId.LessGreater;
 1164                    }
 39165                     else if (_ch == '<')
 25166                    {
 25167                        NextChar();
 25168                        tokenId = TokenId.DoubleLessThan;
 25169                    }
 170                    else
 14171                    {
 14172                        tokenId = TokenId.LessThan;
 14173                    }
 44174                    break;
 175
 176                case '=':
 198177                    NextChar();
 198178                     if (_ch == '=')
 103179                    {
 103180                        NextChar();
 103181                        tokenId = TokenId.DoubleEqual;
 103182                    }
 95183                     else if (_ch == '>')
 19184                    {
 19185                        NextChar();
 19186                        tokenId = TokenId.Lambda;
 19187                    }
 188                    else
 76189                    {
 76190                        tokenId = TokenId.Equal;
 76191                    }
 198192                    break;
 193
 194                case '>':
 54195                    NextChar();
 54196                     if (_ch == '=')
 4197                    {
 4198                        NextChar();
 4199                        tokenId = TokenId.GreaterThanEqual;
 4200                    }
 50201                     else if (_ch == '>')
 8202                    {
 8203                        NextChar();
 8204                        tokenId = TokenId.DoubleGreaterThan;
 8205                    }
 206                    else
 42207                    {
 42208                        tokenId = TokenId.GreaterThan;
 42209                    }
 54210                    break;
 211
 212                case '?':
 16213                    NextChar();
 16214                     if (_ch == '?')
 6215                    {
 6216                        NextChar();
 6217                        tokenId = TokenId.NullCoalescing;
 6218                    }
 10219                     else if (_ch == '.')
 2220                    {
 2221                        NextChar();
 2222                        tokenId = TokenId.NullPropagation;
 2223                    }
 224                    else
 8225                    {
 8226                        tokenId = TokenId.Question;
 8227                    }
 16228                    break;
 229
 230                case '[':
 8231                    NextChar();
 8232                    tokenId = TokenId.OpenBracket;
 8233                    break;
 234
 235                case ']':
 8236                    NextChar();
 8237                    tokenId = TokenId.CloseBracket;
 8238                    break;
 239
 240                case '|':
 18241                    NextChar();
 18242                     if (_ch == '|')
 1243                    {
 1244                        NextChar();
 1245                        tokenId = TokenId.DoubleBar;
 1246                    }
 247                    else
 17248                    {
 17249                        tokenId = TokenId.Bar;
 17250                    }
 18251                    break;
 252
 253                case '"':
 254                case '\'':
 39255                    char quote = _ch;
 256                    do
 39257                    {
 258                        bool escaped;
 259
 260                        do
 265261                        {
 265262                            escaped = false;
 265263                            NextChar();
 264
 29265                         if (_textPos == _textLen)
 1266                            throw ParseError(_textPos, Res.UnterminatedStringLiteral);
 267
 28268                        NextChar();
 56269                     } while (_ch == quote);
 270
 28271                    tokenId = TokenId.StringLiteral;
 28272                    break;
 273
 274                default:
 1476275                     if (char.IsLetter(_ch) || _ch == '@' || _ch == '_' || _ch == '$' || _ch == '^' || _ch == '~')
 944276                    {
 277                        do
 3976278                        {
 3976279                            NextChar();
 7952280                         } while (char.IsLetterOrDigit(_ch) || _ch == '_');
 944281                        tokenId = TokenId.Identifier;
 944282                        break;
 283                    }
 284
 532285                     if (char.IsDigit(_ch))
 178286                    {
 178287                        tokenId = TokenId.IntegerLiteral;
 288                        do
 249289                        {
 249290                            NextChar();
 498291                         } while (char.IsDigit(_ch));
 265265                             if (_ch == '\\')
 8266                            {
 8267                                escaped = true;
 16268                                 if (_textPos < _textLen) NextChar();
 8269                            }
 265270                        }
 265271                         while (_textPos < _textLen && (_ch != quote || escaped));
 272
 39273                         if (_textPos == _textLen)
 1274                            throw ParseError(_textPos, Res.UnterminatedStringLiteral);
 275
 38276                        NextChar();
 76277                     } while (_ch == quote);
 278
 38279                    tokenId = TokenId.StringLiteral;
 38280                    break;
 281
 282                default:
 2065283                     if (char.IsLetter(_ch) || _ch == '@' || _ch == '_' || _ch == '$' || _ch == '^' || _ch == '~')
 1356284                    {
 285                        do
 5496286                        {
 5496287                            NextChar();
 10992288                         } while (char.IsLetterOrDigit(_ch) || _ch == '_');
 1356289                        tokenId = TokenId.Identifier;
 1356290                        break;
 291                    }
 292
 178293                        bool hexInteger = false;
 178294                         if (_ch == 'X' || _ch == 'x')
 9295                        {
 9296                            NextChar();
 9297                            ValidateHexChar();
 298                            do
 78299                            {
 78300                                NextChar();
 156301                             } while (IsHexChar(_ch));
 302
 7303                            hexInteger = true;
 7304                        }
 305
 176306                         if (_ch == 'U' || _ch == 'L')
 21307                        {
 21308                            NextChar();
 21309                             if (_ch == 'L')
 6310                            {
 10311                                 if (_text[_textPos - 1] == 'U') NextChar();
 2312                                else throw ParseError(_textPos, Res.InvalidIntegerQualifier, _text.Substring(_textPos - 
 4313                            }
 19314                            ValidateExpression();
 15315                            break;
 316                        }
 317
 155318                         if (hexInteger)
 2319                        {
 2320                            break;
 321                        }
 322
 153323                         if (_ch == NumberDecimalSeparator)
 15324                        {
 15325                            tokenId = TokenId.RealLiteral;
 15326                            NextChar();
 15327                            ValidateDigit();
 328                            do
 19329                            {
 19330                                NextChar();
 38331                             } while (char.IsDigit(_ch));
 14332                        }
 333
 152334                         if (_ch == 'E' || _ch == 'e')
 3335                        {
 3336                            tokenId = TokenId.RealLiteral;
 3337                            NextChar();
 5338                             if (_ch == '+' || _ch == '-') NextChar();
 3339                            ValidateDigit();
 340                            do
 6341                            {
 6342                                NextChar();
 12343                             } while (char.IsDigit(_ch));
 3344                        }
 345
 160346                         if (_ch == 'F' || _ch == 'f') NextChar();
 160347                         if (_ch == 'D' || _ch == 'd') NextChar();
 152348                        break;
 349                    }
 350
 354351                     if (_textPos == _textLen)
 353352                    {
 353353                        tokenId = TokenId.End;
 353354                        break;
 355                    }
 356
 1357                    throw ParseError(_textPos, Res.InvalidCharacter, _ch);
 358            }
 709293                     if (char.IsDigit(_ch))
 237294                    {
 237295                        tokenId = TokenId.IntegerLiteral;
 296                        do
 323297                        {
 323298                            NextChar();
 646299                         } while (char.IsDigit(_ch));
 300
 237301                        bool hexInteger = false;
 237302                         if (_ch == 'X' || _ch == 'x')
 9303                        {
 9304                            NextChar();
 9305                            ValidateHexChar();
 306                            do
 78307                            {
 78308                                NextChar();
 156309                             } while (IsHexChar(_ch));
 310
 7311                            hexInteger = true;
 7312                        }
 313
 235314                         if (_ch == 'U' || _ch == 'L')
 21315                        {
 21316                            NextChar();
 21317                             if (_ch == 'L')
 6318                            {
 10319                                 if (_text[_textPos - 1] == 'U') NextChar();
 2320                                else throw ParseError(_textPos, Res.InvalidIntegerQualifier, _text.Substring(_textPos - 
 4321                            }
 19322                            ValidateExpression();
 15323                            break;
 324                        }
 325
 214326                         if (hexInteger)
 2327                        {
 2328                            break;
 329                        }
 330
 212331                         if (_ch == NumberDecimalSeparator)
 25332                        {
 25333                            tokenId = TokenId.RealLiteral;
 25334                            NextChar();
 25335                            ValidateDigit();
 336                            do
 34337                            {
 34338                                NextChar();
 68339                             } while (char.IsDigit(_ch));
 24340                        }
 341
 211342                         if (_ch == 'E' || _ch == 'e')
 3343                        {
 3344                            tokenId = TokenId.RealLiteral;
 3345                            NextChar();
 5346                             if (_ch == '+' || _ch == '-') NextChar();
 3347                            ValidateDigit();
 348                            do
 6349                            {
 6350                                NextChar();
 12351                             } while (char.IsDigit(_ch));
 3352                        }
 353
 221354                         if (_ch == 'F' || _ch == 'f') NextChar();
 220355                         if (_ch == 'D' || _ch == 'd') NextChar();
 221356                         if (_ch == 'M' || _ch == 'm') NextChar();
 211357                        break;
 358                    }
 359
 2336360            CurrentToken.Pos = tokenPos;
 2336361            CurrentToken.Text = _text.Substring(tokenPos, _textPos - tokenPos);
 2336362            CurrentToken.OriginalId = tokenId;
 2336363            CurrentToken.Id = GetAliasedTokenId(tokenId, CurrentToken.Text);
 2336364        }
 472360                     if (_textPos == _textLen)
 471361                    {
 471362                        tokenId = TokenId.End;
 471363                        break;
 364                    }
 365
 366        public void ValidateToken(TokenId t, string errorMessage)
 995367        {
 1000368             if (CurrentToken.Id != t) throw ParseError(errorMessage);
 990369        }
 370
 371        public void ValidateToken(TokenId t)
 855372        {
 855373             if (CurrentToken.Id != t) throw ParseError(Res.SyntaxError);
 855374        }
 375
 376        private void ValidateExpression()
 19377        {
 23378             if (char.IsLetterOrDigit(_ch)) throw ParseError(_textPos, Res.ExpressionExpected);
 15379        }
 380
 381        private void ValidateDigit()
 18382        {
 19383             if (!char.IsDigit(_ch)) throw ParseError(_textPos, Res.DigitExpected);
 17384        }
 385
 386        private void ValidateHexChar()
 9387        {
 11388             if (!IsHexChar(_ch)) throw ParseError(_textPos, Res.HexCharExpected);
 7389        }
 1366                    throw ParseError(_textPos, Res.InvalidCharacter, _ch);
 367            }
 368
 3372369            CurrentToken.Pos = tokenPos;
 3372370            CurrentToken.Text = _text.Substring(tokenPos, _textPos - tokenPos);
 3372371            CurrentToken.OriginalId = tokenId;
 3372372            CurrentToken.Id = GetAliasedTokenId(tokenId, CurrentToken.Text);
 3372373        }
 374
 375        public void ValidateToken(TokenId t, string errorMessage)
 1428376        {
 1428377             if (CurrentToken.Id != t)
 5378            {
 5379                throw ParseError(errorMessage);
 380            }
 1423381        }
 382
 383        public void ValidateToken(TokenId t)
 1159384        {
 1159385             if (CurrentToken.Id != t)
 0386            {
 0387                throw ParseError(Res.SyntaxError);
 388            }
 1159389        }
 390
 391        private Exception ParseError(string format, params object[] args)
 5392        {
 5393            return ParseError(CurrentToken.Pos, format, args);
 5394        }
 395
 396        private static Exception ParseError(int pos, string format, params object[] args)
 16397        {
 16398            return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos);
 16399        }
 400
 401        private static TokenId GetAliasedTokenId(TokenId t, string alias)
 2336402        {
 403            TokenId id;
 2336404             return t == TokenId.Identifier && _predefinedAliases.TryGetValue(alias, out id) ? id : t;
 2336405        }
 391        private void ValidateExpression()
 19392        {
 19393             if (char.IsLetterOrDigit(_ch))
 4394            {
 4395                throw ParseError(_textPos, Res.ExpressionExpected);
 396            }
 15397        }
 398
 399        private void ValidateDigit()
 28400        {
 28401             if (!char.IsDigit(_ch))
 1402            {
 1403                throw ParseError(_textPos, Res.DigitExpected);
 404            }
 27405        }
 406
 407        private static bool IsHexChar(char c)
 87408        {
 87409             if (char.IsDigit(c))
 46410            {
 46411                return true;
 407        private void ValidateHexChar()
 9408        {
 9409             if (!IsHexChar(_ch))
 2410            {
 2411                throw ParseError(_textPos, Res.HexCharExpected);
 412            }
 413
 41414             if (c <= '\x007f')
 41415            {
 41416                c |= (char)0x20;
 41417                return c >= 'a' && c <= 'f';
 418            }
 7413        }
 414
 415        private Exception ParseError(string format, params object[] args)
 5416        {
 5417            return ParseError(CurrentToken.Pos, format, args);
 5418        }
 419
 0420            return false;
 87421        }
 422    }
 423}
 420        private static Exception ParseError(int pos, string format, params object[] args)
 16421        {
 16422            return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos);
 16423        }
 424
 425        private static TokenId GetAliasedTokenId(TokenId t, string alias)
 3372426        {
 427            TokenId id;
 3372428             return t == TokenId.Identifier && _predefinedAliases.TryGetValue(alias, out id) ? id : t;
 3372429        }
 430
 431        private static bool IsHexChar(char c)
 87432        {
 87433             if (char.IsDigit(c))
 46434            {
 46435                return true;
 436            }
 437
 41438             if (c <= '\x007f')
 41439            {
 41440                c |= (char)0x20;
 41441                return c >= 'a' && c <= 'f';
 442            }
 443
 0444            return false;
 87445        }
 446    }
 447}
- +

Methods/Properties

@@ -483,15 +507,15 @@

Methods/Properties

SetTextPos(System.Int32)
NextChar()
NextToken()
-ValidateToken(System.Linq.Dynamic.Core.Tokenizer.TokenId,System.String)
-ValidateToken(System.Linq.Dynamic.Core.Tokenizer.TokenId)
-ValidateExpression()
-ValidateDigit()
-ValidateHexChar()
-ParseError(System.String,System.Object[])
-ParseError(System.Int32,System.String,System.Object[])
-GetAliasedTokenId(System.Linq.Dynamic.Core.Tokenizer.TokenId,System.String)
-IsHexChar(System.Char)
+ValidateToken(System.Linq.Dynamic.Core.Tokenizer.TokenId,System.String)
+ValidateToken(System.Linq.Dynamic.Core.Tokenizer.TokenId)
+ValidateExpression()
+ValidateDigit()
+ValidateHexChar()
+ParseError(System.String,System.Object[])
+ParseError(System.Int32,System.String,System.Object[])
+GetAliasedTokenId(System.Linq.Dynamic.Core.Tokenizer.TokenId,System.String)
+IsHexChar(System.Char)

diff --git a/report/System.Linq.Dynamic.Core_Token.htm b/report/System.Linq.Dynamic.Core_Token.htm index 5ca72137..3e502520 100644 --- a/report/System.Linq.Dynamic.Core_Token.htm +++ b/report/System.Linq.Dynamic.Core_Token.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.Tokenizer.Token Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\Token.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\Token.cs Covered lines:4 Uncovered lines:0 Coverable lines:4 @@ -24,7 +24,7 @@

Summary

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\Token.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Tokenizer\Token.cs

@@ -32,18 +32,18 @@

- + - + - + - +
#LineLine coverage
 2{
 3    internal struct Token
 4    {
 284685        public TokenId Id { get; set; }
 412435        public TokenId Id { get; set; }
 6
 23367        public TokenId OriginalId { get; set; }
 33727        public TokenId OriginalId { get; set; }
 8
 78909        public string Text { get; set; }
 110119        public string Text { get; set; }
 10
 403711        public int Pos { get; set; }
 556911        public int Pos { get; set; }
 12    }
 13}
- +

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_TypeConverterFactory.htm b/report/System.Linq.Dynamic.Core_TypeConverterFactory.htm index d8289074..01f1fc57 100644 --- a/report/System.Linq.Dynamic.Core_TypeConverterFactory.htm +++ b/report/System.Linq.Dynamic.Core_TypeConverterFactory.htm @@ -15,7 +15,7 @@

Summary

Class:System.Linq.Dynamic.Core.TypeConverterFactory Assembly:System.Linq.Dynamic.Core -File(s):C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\TypeConverterFactory.cs +File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\TypeConverterFactory.cs Covered lines:4 Uncovered lines:0 Coverable lines:4 @@ -31,7 +31,7 @@

Metrics

File(s)

-

C:\Users\Stef\Documents\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\TypeConverterFactory.cs

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\TypeConverterFactory.cs

@@ -73,7 +73,7 @@

#LineLine coverage
 36}
-
+

Methods/Properties

diff --git a/report/System.Linq.Dynamic.Core_TypeHelper.htm b/report/System.Linq.Dynamic.Core_TypeHelper.htm new file mode 100644 index 00000000..4b464378 --- /dev/null +++ b/report/System.Linq.Dynamic.Core_TypeHelper.htm @@ -0,0 +1,585 @@ + + + + + +System.Linq.Dynamic.Core.Parser.TypeHelper - Coverage Report + +
+

Summary

+ ++++ + + + + + + + + + + + +
Class:System.Linq.Dynamic.Core.Parser.TypeHelper
Assembly:System.Linq.Dynamic.Core
File(s):C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\TypeHelper.cs
Covered lines:194
Uncovered lines:18
Coverable lines:212
Total lines:506
Line coverage:91.5%
Branch coverage:87%
+

Metrics

+ + + + + + + + + + + + + + + + + + + + +
MethodCyclomatic complexity  NPath complexity  Sequence coverage  Branch coverage  
FindGenericType(...)81610088.89
IsCompatibleWith(...)7116777216100100
IsEnumType(...)10100100
IsNumericType(...)10100100
IsNullableType(...)20100100
IsSignedIntegralType(...)10100100
IsUnsignedIntegralType(...)10100100
GetNumericTypeKind(...)141684.6288.89
GetTypeName(...)2266.6766.67
GetNonNullableType(...)32100100
GetUnderlyingType(...)44100100
GetSelfAndBaseTypes(...)22100100
AddInterface(...)32100100
ParseNumber(...)23419430471.1971.11
ParseEnum(...)32100100
GetSelfAndBaseClasses()42100100
+

File(s)

+

C:\Users\azureuser\Documents\Github\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\TypeHelper.cs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#LineLine coverage
 1using System.Collections.Generic;
 2using System.Linq.Dynamic.Core.Validation;
 3using System.Reflection;
 4
 5namespace System.Linq.Dynamic.Core.Parser
 6{
 7    internal static class TypeHelper
 8    {
 9        public static Type FindGenericType(Type generic, Type type)
 162010        {
 296011             while (type != null && type != typeof(object))
 162412            {
 162413                 if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == generic)
 9914                {
 9915                    return type;
 16                }
 17
 152518                 if (generic.GetTypeInfo().IsInterface)
 152519                {
 727620                    foreach (Type intfType in type.GetInterfaces())
 144321                    {
 144322                        Type found = FindGenericType(generic, intfType);
 162823                         if (found != null) return found;
 125824                    }
 134025                }
 26
 134027                type = type.GetTypeInfo().BaseType;
 134028            }
 29
 133630            return null;
 162031        }
 32
 33        public static bool IsCompatibleWith(Type source, Type target)
 481034        {
 35#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 36            if (source == target)
 37            {
 38                return true;
 39            }
 40
 41            if (!target.IsValueType)
 42            {
 43                return target.IsAssignableFrom(source);
 44            }
 45
 46            Type st = GetNonNullableType(source);
 47            Type tt = GetNonNullableType(target);
 48
 49            if (st != source && tt == target)
 50            {
 51                return false;
 52            }
 53
 54            TypeCode sc = st.GetTypeInfo().IsEnum ? TypeCode.Object : Type.GetTypeCode(st);
 55            TypeCode tc = tt.GetTypeInfo().IsEnum ? TypeCode.Object : Type.GetTypeCode(tt);
 56            switch (sc)
 57            {
 58                case TypeCode.SByte:
 59                    switch (tc)
 60                    {
 61                        case TypeCode.SByte:
 62                        case TypeCode.Int16:
 63                        case TypeCode.Int32:
 64                        case TypeCode.Int64:
 65                        case TypeCode.Single:
 66                        case TypeCode.Double:
 67                        case TypeCode.Decimal:
 68                            return true;
 69                    }
 70                    break;
 71                case TypeCode.Byte:
 72                    switch (tc)
 73                    {
 74                        case TypeCode.Byte:
 75                        case TypeCode.Int16:
 76                        case TypeCode.UInt16:
 77                        case TypeCode.Int32:
 78                        case TypeCode.UInt32:
 79                        case TypeCode.Int64:
 80                        case TypeCode.UInt64:
 81                        case TypeCode.Single:
 82                        case TypeCode.Double:
 83                        case TypeCode.Decimal:
 84                            return true;
 85                    }
 86                    break;
 87                case TypeCode.Int16:
 88                    switch (tc)
 89                    {
 90                        case TypeCode.Int16:
 91                        case TypeCode.Int32:
 92                        case TypeCode.Int64:
 93                        case TypeCode.Single:
 94                        case TypeCode.Double:
 95                        case TypeCode.Decimal:
 96                            return true;
 97                    }
 98                    break;
 99                case TypeCode.UInt16:
 100                    switch (tc)
 101                    {
 102                        case TypeCode.UInt16:
 103                        case TypeCode.Int32:
 104                        case TypeCode.UInt32:
 105                        case TypeCode.Int64:
 106                        case TypeCode.UInt64:
 107                        case TypeCode.Single:
 108                        case TypeCode.Double:
 109                        case TypeCode.Decimal:
 110                            return true;
 111                    }
 112                    break;
 113                case TypeCode.Int32:
 114                    switch (tc)
 115                    {
 116                        case TypeCode.Int32:
 117                        case TypeCode.Int64:
 118                        case TypeCode.Single:
 119                        case TypeCode.Double:
 120                        case TypeCode.Decimal:
 121                            return true;
 122                    }
 123                    break;
 124                case TypeCode.UInt32:
 125                    switch (tc)
 126                    {
 127                        case TypeCode.UInt32:
 128                        case TypeCode.Int64:
 129                        case TypeCode.UInt64:
 130                        case TypeCode.Single:
 131                        case TypeCode.Double:
 132                        case TypeCode.Decimal:
 133                            return true;
 134                    }
 135                    break;
 136                case TypeCode.Int64:
 137                    switch (tc)
 138                    {
 139                        case TypeCode.Int64:
 140                        case TypeCode.Single:
 141                        case TypeCode.Double:
 142                        case TypeCode.Decimal:
 143                            return true;
 144                    }
 145                    break;
 146                case TypeCode.UInt64:
 147                    switch (tc)
 148                    {
 149                        case TypeCode.UInt64:
 150                        case TypeCode.Single:
 151                        case TypeCode.Double:
 152                        case TypeCode.Decimal:
 153                            return true;
 154                    }
 155                    break;
 156                case TypeCode.Single:
 157                    switch (tc)
 158                    {
 159                        case TypeCode.Single:
 160                        case TypeCode.Double:
 161                            return true;
 162                    }
 163                    break;
 164                default:
 165                    if (st == tt)
 166                    {
 167                        return true;
 168                    }
 169                    break;
 170            }
 171            return false;
 172#else
 4810173             if (source == target)
 1174            {
 1175                return true;
 176            }
 4809177             if (!target.GetTypeInfo().IsValueType)
 246178            {
 246179                return target.IsAssignableFrom(source);
 180            }
 4563181            Type st = GetNonNullableType(source);
 4563182            Type tt = GetNonNullableType(target);
 183
 4563184             if (st != source && tt == target)
 594185            {
 594186                return false;
 187            }
 3969188             Type sc = st.GetTypeInfo().IsEnum ? typeof(Object) : st;
 3969189             Type tc = tt.GetTypeInfo().IsEnum ? typeof(Object) : tt;
 190
 3969191             if (sc == typeof(SByte))
 120192            {
 120193                 if (tc == typeof(SByte) || tc == typeof(Int16) || tc == typeof(Int32) || tc == typeof(Int64) || tc == ty
 52194                    return true;
 68195            }
 3849196             else if (sc == typeof(Byte))
 121197            {
 121198                 if (tc == typeof(Byte) || tc == typeof(Int16) || tc == typeof(UInt16) || tc == typeof(Int32) || tc == ty
 93199                    return true;
 28200            }
 3728201             else if (sc == typeof(Int16))
 149202            {
 149203                 if (tc == typeof(Int16) || tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == t
 63204                    return true;
 86205            }
 3579206             else if (sc == typeof(UInt16))
 120207            {
 120208                 if (tc == typeof(UInt16) || tc == typeof(Int32) || tc == typeof(UInt32) || tc == typeof(Int64) || tc == 
 92209                    return true;
 28210            }
 3459211             else if (sc == typeof(Int32))
 1213212            {
 1213213                 if (tc == typeof(Int32) || tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == 
 838214                    return true;
 375215            }
 2246216             else if (sc == typeof(UInt32))
 271217            {
 271218                 if (tc == typeof(UInt32) || tc == typeof(Int64) || tc == typeof(UInt64) || tc == typeof(Single) || tc ==
 117219                    return true;
 154220            }
 1975221             else if (sc == typeof(Int64))
 494222            {
 494223                 if (tc == typeof(Int64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
 187224                    return true;
 307225            }
 1481226             else if (sc == typeof(UInt64))
 278227            {
 278228                 if (tc == typeof(UInt64) || tc == typeof(Single) || tc == typeof(Double) || tc == typeof(Decimal))
 64229                    return true;
 214230            }
 1203231             else if (sc == typeof(Single))
 292232            {
 292233                 if (tc == typeof(Single) || tc == typeof(Double))
 70234                    return true;
 222235            }
 236
 2393237             if (st == tt)
 128238            {
 128239                return true;
 240            }
 241
 2265242            return false;
 243#endif
 4810244        }
 245
 246        public static bool IsEnumType(Type type)
 406247        {
 406248            return GetNonNullableType(type).GetTypeInfo().IsEnum;
 406249        }
 250
 251        public static bool IsNumericType(Type type)
 13252        {
 13253            return GetNumericTypeKind(type) != 0;
 13254        }
 255
 256        public static bool IsNullableType(Type type)
 12010257        {
 12010258            Check.NotNull(type, nameof(type));
 259
 12010260            return type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
 12010261        }
 262
 263        public static bool IsSignedIntegralType(Type type)
 670264        {
 670265            return GetNumericTypeKind(type) == 2;
 670266        }
 267
 268        public static bool IsUnsignedIntegralType(Type type)
 250269        {
 250270            return GetNumericTypeKind(type) == 3;
 250271        }
 272
 273        private static int GetNumericTypeKind(Type type)
 933274        {
 933275            type = GetNonNullableType(type);
 276
 277#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 278            if (type.GetTypeInfo().IsEnum)
 279            {
 280                return 0;
 281            }
 282
 283            switch (Type.GetTypeCode(type))
 284            {
 285                case TypeCode.Char:
 286                case TypeCode.Single:
 287                case TypeCode.Double:
 288                case TypeCode.Decimal:
 289                    return 1;
 290                case TypeCode.SByte:
 291                case TypeCode.Int16:
 292                case TypeCode.Int32:
 293                case TypeCode.Int64:
 294                    return 2;
 295                case TypeCode.Byte:
 296                case TypeCode.UInt16:
 297                case TypeCode.UInt32:
 298                case TypeCode.UInt64:
 299                    return 3;
 300                default:
 301                    return 0;
 302            }
 303#else
 933304             if (type.GetTypeInfo().IsEnum)
 0305            {
 0306                return 0;
 307            }
 308
 933309             if (type == typeof(Char) || type == typeof(Single) || type == typeof(Double) || type == typeof(Decimal))
 398310                return 1;
 535311             if (type == typeof(SByte) || type == typeof(Int16) || type == typeof(Int32) || type == typeof(Int64))
 276312                return 2;
 259313             if (type == typeof(Byte) || type == typeof(UInt16) || type == typeof(UInt32) || type == typeof(UInt64))
 243314                return 3;
 315
 16316            return 0;
 317#endif
 933318        }
 319
 320        public static string GetTypeName(Type type)
 16321        {
 16322            Type baseType = GetNonNullableType(type);
 323
 16324            string s = baseType.Name;
 16325             if (type != baseType)
 0326            {
 0327                s += '?';
 0328            }
 16329            return s;
 16330        }
 331
 332        public static Type GetNonNullableType(Type type)
 11914333        {
 11914334            Check.NotNull(type, nameof(type));
 335
 11914336             return IsNullableType(type) ? type.GetTypeInfo().GetGenericTypeArguments()[0] : type;
 11914337        }
 338
 339        public static Type GetUnderlyingType(Type type)
 240340        {
 240341            Check.NotNull(type, nameof(type));
 342
 240343            Type[] genericTypeArguments = type.GetGenericArguments();
 240344             if (genericTypeArguments.Any())
 168345            {
 168346                var outerType = GetUnderlyingType(genericTypeArguments.LastOrDefault());
 168347                 return Nullable.GetUnderlyingType(type) == outerType ? type : outerType;
 348            }
 349
 72350            return type;
 240351        }
 352
 353        public static IEnumerable<Type> GetSelfAndBaseTypes(Type type)
 439354        {
 439355             if (type.GetTypeInfo().IsInterface)
 19356            {
 19357                var types = new List<Type>();
 19358                AddInterface(types, type);
 19359                return types;
 360            }
 420361            return GetSelfAndBaseClasses(type);
 439362        }
 363
 364        private static IEnumerable<Type> GetSelfAndBaseClasses(Type type)
 420365        {
 462366             while (type != null)
 442367            {
 442368                yield return type;
 42369                type = type.GetTypeInfo().BaseType;
 42370            }
 20371        }
 372
 373        private static void AddInterface(List<Type> types, Type type)
 76374        {
 76375             if (!types.Contains(type))
 57376            {
 57377                types.Add(type);
 285378                foreach (Type t in type.GetInterfaces())
 57379                {
 57380                    AddInterface(types, t);
 57381                }
 57382            }
 76383        }
 384
 385        public static object ParseNumber(string text, Type type)
 707386        {
 387#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
 388            switch (Type.GetTypeCode(GetNonNullableType(type)))
 389            {
 390                case TypeCode.SByte:
 391                    sbyte sb;
 392                    if (SByte.TryParse(text, out sb)) return sb;
 393                    break;
 394                case TypeCode.Byte:
 395                    byte b;
 396                    if (Byte.TryParse(text, out b)) return b;
 397                    break;
 398                case TypeCode.Int16:
 399                    short s;
 400                    if (Int16.TryParse(text, out s)) return s;
 401                    break;
 402                case TypeCode.UInt16:
 403                    ushort us;
 404                    if (UInt16.TryParse(text, out us)) return us;
 405                    break;
 406                case TypeCode.Int32:
 407                    int i;
 408                    if (Int32.TryParse(text, out i)) return i;
 409                    break;
 410                case TypeCode.UInt32:
 411                    uint ui;
 412                    if (UInt32.TryParse(text, out ui)) return ui;
 413                    break;
 414                case TypeCode.Int64:
 415                    long l;
 416                    if (Int64.TryParse(text, out l)) return l;
 417                    break;
 418                case TypeCode.UInt64:
 419                    ulong ul;
 420                    if (UInt64.TryParse(text, out ul)) return ul;
 421                    break;
 422                case TypeCode.Single:
 423                    float f;
 424                    if (Single.TryParse(text, out f)) return f;
 425                    break;
 426                case TypeCode.Double:
 427                    double d;
 428                    if (Double.TryParse(text, out d)) return d;
 429                    break;
 430                case TypeCode.Decimal:
 431                    decimal e;
 432                    if (Decimal.TryParse(text, out e)) return e;
 433                    break;
 434            }
 435#else
 707436            var tp = GetNonNullableType(type);
 707437             if (tp == typeof(SByte))
 0438            {
 439                sbyte sb;
 0440                 if (sbyte.TryParse(text, out sb)) return sb;
 0441            }
 707442             else if (tp == typeof(Byte))
 0443            {
 444                byte b;
 0445                 if (byte.TryParse(text, out b)) return b;
 0446            }
 707447             else if (tp == typeof(Int16))
 0448            {
 449                short s;
 0450                 if (short.TryParse(text, out s)) return s;
 0451            }
 707452             else if (tp == typeof(UInt16))
 0453            {
 454                ushort us;
 0455                 if (ushort.TryParse(text, out us)) return us;
 0456            }
 707457             else if (tp == typeof(Int32))
 150458            {
 459                int i;
 294460                 if (int.TryParse(text, out i)) return i;
 6461            }
 557462             else if (tp == typeof(UInt32))
 31463            {
 464                uint ui;
 62465                 if (uint.TryParse(text, out ui)) return ui;
 0466            }
 526467             else if (tp == typeof(Int64))
 96468            {
 469                long l;
 186470                 if (long.TryParse(text, out l)) return l;
 6471            }
 430472             else if (tp == typeof(UInt64))
 45473            {
 474                ulong ul;
 89475                 if (ulong.TryParse(text, out ul)) return ul;
 1476            }
 385477             else if (tp == typeof(Single))
 116478            {
 479                float f;
 222480                 if (float.TryParse(text, out f)) return f;
 10481            }
 269482             else if (tp == typeof(Double))
 128483            {
 484                double d;
 246485                 if (double.TryParse(text, out d)) return d;
 10486            }
 141487             else if (tp == typeof(Decimal))
 121488            {
 489                decimal e;
 232490                 if (decimal.TryParse(text, out e)) return e;
 10491            }
 492#endif
 63493            return null;
 707494        }
 495
 496        public static object ParseEnum(string value, Type type)
 3497        {
 3498             if (type.GetTypeInfo().IsEnum && Enum.IsDefined(type, value))
 1499            {
 1500                return Enum.Parse(type, value, true);
 501            }
 502
 2503            return null;
 3504        }
 505    }
 506}
+
+
+ + \ No newline at end of file diff --git a/report/combined.js b/report/combined.js index 1fc8a093..87f27330 100644 --- a/report/combined.js +++ b/report/combined.js @@ -314,7 +314,8 @@ var assemblies = [ { "name" : "Microsoft.EntityFrameworkCore.DynamicLinq", "classes" : [ - { "name" : "Microsoft.EntityFrameworkCore.DynamicLinq.EntityFrameworkDynamicQueryableExtensions", "reportPath" : "Microsoft.EntityFrameworkCore.DynamicLinq_EntityFrameworkDynamicQueryableExtensions.htm", "coveredLines" : 96, "uncoveredLines" : 42, "coverableLines" : 138, "totalLines" : 639, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 5, "totalBranches" : 10, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "Microsoft.EntityFrameworkCore.DynamicLinq.DynamicFunctions", "reportPath" : "Microsoft.EntityFrameworkCore.DynamicLinq_DynamicFunctions.htm", "coveredLines" : 0, "uncoveredLines" : 0, "coverableLines" : 0, "totalLines" : 0, "coverageType" : "MethodCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "Microsoft.EntityFrameworkCore.DynamicLinq.EntityFrameworkDynamicQueryableExtensions", "reportPath" : "Microsoft.EntityFrameworkCore.DynamicLinq_EntityFrameworkDynamicQueryableExtensions.htm", "coveredLines" : 96, "uncoveredLines" : 42, "coverableLines" : 138, "totalLines" : 654, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 5, "totalBranches" : 10, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Extensions.LinqProviderExtensions", "reportPath" : "Microsoft.EntityFrameworkCore.DynamicLinq_LinqProviderExtensions.htm", "coveredLines" : 0, "uncoveredLines" : 22, "coverableLines" : 22, "totalLines" : 51, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 6, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Res", "reportPath" : "Microsoft.EntityFrameworkCore.DynamicLinq_Res.htm", "coveredLines" : 0, "uncoveredLines" : 0, "coverableLines" : 0, "totalLines" : 0, "coverageType" : "MethodCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Validation.Check", "reportPath" : "Microsoft.EntityFrameworkCore.DynamicLinq_Check.htm", "coveredLines" : 11, "uncoveredLines" : 60, "coverableLines" : 71, "totalLines" : 139, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 4, "totalBranches" : 20, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, @@ -327,26 +328,38 @@ var assemblies = [ "classes" : [ { "name" : "System.Linq.Dynamic.Core.AssemblyBuilderFactory", "reportPath" : "System.Linq.Dynamic.Core_AssemblyBuilderFactory.htm", "coveredLines" : 3, "uncoveredLines" : 0, "coverableLines" : 3, "totalLines" : 25, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.CustomTypeProviders.AbstractDynamicLinqCustomTypeProvider", "reportPath" : "System.Linq.Dynamic.Core_AbstractDynamicLinqCustomTypeProvider.htm", "coveredLines" : 23, "uncoveredLines" : 2, "coverableLines" : 25, "totalLines" : 95, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 1, "totalBranches" : 2, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.CustomTypeProviders.DefaultDynamicLinqCustomTypeProvider", "reportPath" : "System.Linq.Dynamic.Core_DefaultDynamicLinqCustomTypeProvider.htm", "coveredLines" : 0, "uncoveredLines" : 8, "coverableLines" : 8, "totalLines" : 32, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 2, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.CustomTypeProviders.DefaultDynamicLinqCustomTypeProvider", "reportPath" : "System.Linq.Dynamic.Core_DefaultDynamicLinqCustomTypeProvider.htm", "coveredLines" : 0, "uncoveredLines" : 9, "coverableLines" : 9, "totalLines" : 34, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 2, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.CustomTypeProviders.DynamicLinqTypeAttribute", "reportPath" : "System.Linq.Dynamic.Core_DynamicLinqTypeAttribute.htm", "coveredLines" : 0, "uncoveredLines" : 0, "coverableLines" : 0, "totalLines" : 0, "coverageType" : "MethodCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.DefaultAssemblyHelper", "reportPath" : "System.Linq.Dynamic.Core_DefaultAssemblyHelper.htm", "coveredLines" : 0, "uncoveredLines" : 2, "coverableLines" : 2, "totalLines" : 44, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.DynamicClass", "reportPath" : "System.Linq.Dynamic.Core_DynamicClass.htm", "coveredLines" : 5, "uncoveredLines" : 51, "coverableLines" : 56, "totalLines" : 328, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 10, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.DynamicClassFactory", "reportPath" : "System.Linq.Dynamic.Core_DynamicClassFactory.htm", "coveredLines" : 200, "uncoveredLines" : 15, "coverableLines" : 215, "totalLines" : 375, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 26, "totalBranches" : 34, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.DynamicClass", "reportPath" : "System.Linq.Dynamic.Core_DynamicClass.htm", "coveredLines" : 5, "uncoveredLines" : 60, "coverableLines" : 65, "totalLines" : 178, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 10, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.DynamicClassFactory", "reportPath" : "System.Linq.Dynamic.Core_DynamicClassFactory.htm", "coveredLines" : 204, "uncoveredLines" : 15, "coverableLines" : 219, "totalLines" : 390, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 27, "totalBranches" : 34, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.DynamicEnumerableAsyncExtensions", "reportPath" : "System.Linq.Dynamic.Core_DynamicEnumerableAsyncExtensions.htm", "coveredLines" : 0, "uncoveredLines" : 32, "coverableLines" : 32, "totalLines" : 106, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.DynamicEnumerableExtensions", "reportPath" : "System.Linq.Dynamic.Core_DynamicEnumerableExtensions.htm", "coveredLines" : 37, "uncoveredLines" : 0, "coverableLines" : 37, "totalLines" : 135, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.DynamicExpressionParser", "reportPath" : "System.Linq.Dynamic.Core_DynamicExpressionParser.htm", "coveredLines" : 26, "uncoveredLines" : 0, "coverableLines" : 26, "totalLines" : 110, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.DynamicExpressionParser", "reportPath" : "System.Linq.Dynamic.Core_DynamicExpressionParser.htm", "coveredLines" : 38, "uncoveredLines" : 16, "coverableLines" : 54, "totalLines" : 242, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.DynamicGetMemberBinder", "reportPath" : "System.Linq.Dynamic.Core_DynamicGetMemberBinder.htm", "coveredLines" : 0, "uncoveredLines" : 11, "coverableLines" : 11, "totalLines" : 34, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 2, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.DynamicOrdering", "reportPath" : "System.Linq.Dynamic.Core_DynamicOrdering.htm", "coveredLines" : 0, "uncoveredLines" : 0, "coverableLines" : 0, "totalLines" : 0, "coverageType" : "MethodCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.DynamicProperty", "reportPath" : "System.Linq.Dynamic.Core_DynamicProperty.htm", "coveredLines" : 7, "uncoveredLines" : 0, "coverableLines" : 7, "totalLines" : 35, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.DynamicQueryableExtensions", "reportPath" : "System.Linq.Dynamic.Core_DynamicQueryableExtensions.htm", "coveredLines" : 480, "uncoveredLines" : 14, "coverableLines" : 494, "totalLines" : 1375, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 22, "totalBranches" : 28, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.DynamicQueryableExtensions", "reportPath" : "System.Linq.Dynamic.Core_DynamicQueryableExtensions.htm", "coveredLines" : 731, "uncoveredLines" : 18, "coverableLines" : 749, "totalLines" : 2048, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 28, "totalBranches" : 34, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Exceptions.ParseException", "reportPath" : "System.Linq.Dynamic.Core_ParseException.htm", "coveredLines" : 4, "uncoveredLines" : 4, "coverableLines" : 8, "totalLines" : 66, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.ExpressionParser", "reportPath" : "System.Linq.Dynamic.Core_ExpressionParser.htm", "coveredLines" : 1323, "uncoveredLines" : 187, "coverableLines" : 1510, "totalLines" : 2670, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 531, "totalBranches" : 705, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.ExtensibilityPoint", "reportPath" : "System.Linq.Dynamic.Core_ExtensibilityPoint.htm", "coveredLines" : 1, "uncoveredLines" : 0, "coverableLines" : 1, "totalLines" : 17, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Extensions.LinqProviderExtensions", "reportPath" : "System.Linq.Dynamic.Core_LinqProviderExtensions.htm", "coveredLines" : 19, "uncoveredLines" : 3, "coverableLines" : 22, "totalLines" : 51, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 5, "totalBranches" : 6, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.GlobalConfig", "reportPath" : "System.Linq.Dynamic.Core_GlobalConfig.htm", "coveredLines" : 19, "uncoveredLines" : 1, "coverableLines" : 20, "totalLines" : 66, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 3, "totalBranches" : 4, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.GroupResult", "reportPath" : "System.Linq.Dynamic.Core_GroupResult.htm", "coveredLines" : 7, "uncoveredLines" : 0, "coverableLines" : 7, "totalLines" : 47, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.PagedResult", "reportPath" : "System.Linq.Dynamic.Core_PagedResult.htm", "coveredLines" : 5, "uncoveredLines" : 0, "coverableLines" : 5, "totalLines" : 64, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.PagedResult`1", "reportPath" : "System.Linq.Dynamic.Core_PagedResult_1.htm", "coveredLines" : 1, "uncoveredLines" : 0, "coverableLines" : 1, "totalLines" : 64, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.ParameterExpressionHelper", "reportPath" : "System.Linq.Dynamic.Core_ParameterExpressionHelper.htm", "coveredLines" : 3, "uncoveredLines" : 0, "coverableLines" : 3, "totalLines" : 12, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.ConstantExpressionHelper", "reportPath" : "System.Linq.Dynamic.Core_ConstantExpressionHelper.htm", "coveredLines" : 14, "uncoveredLines" : 0, "coverableLines" : 14, "totalLines" : 29, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 2, "totalBranches" : 2, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.Constants", "reportPath" : "System.Linq.Dynamic.Core_Constants.htm", "coveredLines" : 3, "uncoveredLines" : 0, "coverableLines" : 3, "totalLines" : 11, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.ExpressionHelper", "reportPath" : "System.Linq.Dynamic.Core_ExpressionHelper.htm", "coveredLines" : 120, "uncoveredLines" : 5, "coverableLines" : 125, "totalLines" : 199, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 62, "totalBranches" : 88, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.ExpressionParser", "reportPath" : "System.Linq.Dynamic.Core_ExpressionParser.htm", "coveredLines" : 996, "uncoveredLines" : 194, "coverableLines" : 1190, "totalLines" : 1824, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 375, "totalBranches" : 497, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.ExpressionPromoter", "reportPath" : "System.Linq.Dynamic.Core_ExpressionPromoter.htm", "coveredLines" : 48, "uncoveredLines" : 3, "coverableLines" : 51, "totalLines" : 101, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 26, "totalBranches" : 28, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.KeywordsHelper", "reportPath" : "System.Linq.Dynamic.Core_KeywordsHelper.htm", "coveredLines" : 41, "uncoveredLines" : 0, "coverableLines" : 41, "totalLines" : 67, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 3, "totalBranches" : 4, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.PredefinedTypesHelper", "reportPath" : "System.Linq.Dynamic.Core_PredefinedTypesHelper.htm", "coveredLines" : 45, "uncoveredLines" : 12, "coverableLines" : 57, "totalLines" : 99, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 2, "totalBranches" : 4, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodData", "reportPath" : "System.Linq.Dynamic.Core_MethodData.htm", "coveredLines" : 3, "uncoveredLines" : 0, "coverableLines" : 3, "totalLines" : 12, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodFinder", "reportPath" : "System.Linq.Dynamic.Core_MethodFinder.htm", "coveredLines" : 142, "uncoveredLines" : 6, "coverableLines" : 148, "totalLines" : 229, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 51, "totalBranches" : 56, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Parser.TypeHelper", "reportPath" : "System.Linq.Dynamic.Core_TypeHelper.htm", "coveredLines" : 194, "uncoveredLines" : 18, "coverableLines" : 212, "totalLines" : 506, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 108, "totalBranches" : 124, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.ParsingConfig", "reportPath" : "System.Linq.Dynamic.Core_ParsingConfig.htm", "coveredLines" : 12, "uncoveredLines" : 0, "coverableLines" : 12, "totalLines" : 52, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 1, "totalBranches" : 2, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Res", "reportPath" : "System.Linq.Dynamic.Core_Res.htm", "coveredLines" : 0, "uncoveredLines" : 0, "coverableLines" : 0, "totalLines" : 0, "coverageType" : "MethodCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, - { "name" : "System.Linq.Dynamic.Core.Tokenizer.TextParser", "reportPath" : "System.Linq.Dynamic.Core_TextParser.htm", "coveredLines" : 287, "uncoveredLines" : 1, "coverableLines" : 288, "totalLines" : 423, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 124, "totalBranches" : 132, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, + { "name" : "System.Linq.Dynamic.Core.Tokenizer.TextParser", "reportPath" : "System.Linq.Dynamic.Core_TextParser.htm", "coveredLines" : 303, "uncoveredLines" : 3, "coverableLines" : 306, "totalLines" : 447, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 128, "totalBranches" : 136, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.Tokenizer.Token", "reportPath" : "System.Linq.Dynamic.Core_Token.htm", "coveredLines" : 4, "uncoveredLines" : 0, "coverableLines" : 4, "totalLines" : 13, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Linq.Dynamic.Core.TypeConverterFactory", "reportPath" : "System.Linq.Dynamic.Core_TypeConverterFactory.htm", "coveredLines" : 4, "uncoveredLines" : 0, "coverableLines" : 4, "totalLines" : 36, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, { "name" : "System.Reflection.CustomIntrospectionExtensions", "reportPath" : "System.Linq.Dynamic.Core_CustomIntrospectionExtensions.htm", "coveredLines" : 3, "uncoveredLines" : 0, "coverableLines" : 3, "totalLines" : 39, "coverageType" : "LineCoverage", "methodCoverage" : "-", "coveredBranches" : 0, "totalBranches" : 0, "lineCoverageHistory" : [], "branchCoverageHistory" : [] }, diff --git a/report/index.htm b/report/index.htm index c1361d85..8c61c99d 100644 --- a/report/index.htm +++ b/report/index.htm @@ -13,17 +13,17 @@

Summary

-Generated on:30-4-2017 - 13:27:34 +Generated on:2018-07-27 - 14:51:27 Parser:OpenCoverParser Assemblies:2 -Classes:33 -Files:25 -Covered lines:2568 -Uncovered lines:430 -Coverable lines:2998 -Total lines:7089 -Line coverage:85.6% -Branch coverage:75.1% +Classes:46 +Files:37 +Covered lines:3130 +Uncovered lines:555 +Coverable lines:3685 +Total lines:8345 +Line coverage:84.9% +Branch coverage:77.6%

Assemblies

@@ -45,43 +45,56 @@

Assemblies

NameCoveredUncoveredCoverableTotalLine coverageBranch coverage -Microsoft.EntityFrameworkCore.DynamicLinq10714224994442.9%
  
25%
  
-Microsoft.EntityFrameworkCore.DynamicLinq.EntityFrameworkDynamicQueryableExtensions964213863969.5%
  
50%
  
+Microsoft.EntityFrameworkCore.DynamicLinq10714224995942.9%
  
25%
  
+Microsoft.EntityFrameworkCore.DynamicLinq.DynamicFunctions0000
 
 
+Microsoft.EntityFrameworkCore.DynamicLinq.EntityFrameworkDynamicQueryableExtensions964213865469.5%
  
50%
  
System.Linq.Dynamic.Core.Extensions.LinqProviderExtensions02222510%
 
0%
 
System.Linq.Dynamic.Core.Res0000
 
 
System.Linq.Dynamic.Core.Validation.Check11607113915.4%
  
20%
  
System.Linq.Dynamic.Core.Validation.CoreStrings01212410%
 
 
System.Reflection.CustomIntrospectionExtensions033390%
 
 
System.Reflection.CustomTypeBuilderExtensions033350%
 
 
-System.Linq.Dynamic.Core24612882749614589.5%
  
77.1%
  
+System.Linq.Dynamic.Core30234133436738687.9%
  
79.4%
  
System.Linq.Dynamic.Core.AssemblyBuilderFactory30325100%
 
 
System.Linq.Dynamic.Core.CustomTypeProviders.AbstractDynamicLinqCustomTypeProvider232259592%
  
50%
  
-System.Linq.Dynamic.Core.CustomTypeProviders.DefaultDynamicLinqCustomTypeProvider088320%
 
0%
 
+System.Linq.Dynamic.Core.CustomTypeProviders.DefaultDynamicLinqCustomTypeProvider099340%
 
0%
 
System.Linq.Dynamic.Core.CustomTypeProviders.DynamicLinqTypeAttribute0000
 
 
System.Linq.Dynamic.Core.DefaultAssemblyHelper022440%
 
 
-System.Linq.Dynamic.Core.DynamicClass551563288.9%
  
0%
 
-System.Linq.Dynamic.Core.DynamicClassFactory2001521537593%
  
76.4%
  
+System.Linq.Dynamic.Core.DynamicClass560651787.6%
  
0%
 
+System.Linq.Dynamic.Core.DynamicClassFactory2041521939093.1%
  
79.4%
  
+System.Linq.Dynamic.Core.DynamicEnumerableAsyncExtensions032321060%
 
 
System.Linq.Dynamic.Core.DynamicEnumerableExtensions37037135100%
 
 
-System.Linq.Dynamic.Core.DynamicExpressionParser26026110100%
 
 
+System.Linq.Dynamic.Core.DynamicExpressionParser38165424270.3%
  
 
+System.Linq.Dynamic.Core.DynamicGetMemberBinder01111340%
 
0%
 
System.Linq.Dynamic.Core.DynamicOrdering0000
 
 
System.Linq.Dynamic.Core.DynamicProperty70735100%
 
 
-System.Linq.Dynamic.Core.DynamicQueryableExtensions48014494137597.1%
  
78.5%
  
+System.Linq.Dynamic.Core.DynamicQueryableExtensions73118749204897.5%
  
82.3%
  
System.Linq.Dynamic.Core.Exceptions.ParseException4486650%
  
 
-System.Linq.Dynamic.Core.ExpressionParser13231871510267087.6%
  
75.3%
  
System.Linq.Dynamic.Core.ExtensibilityPoint10117100%
 
 
System.Linq.Dynamic.Core.Extensions.LinqProviderExtensions193225186.3%
  
83.3%
  
-System.Linq.Dynamic.Core.GlobalConfig191206695%
  
75%
  
System.Linq.Dynamic.Core.GroupResult70747100%
 
 
System.Linq.Dynamic.Core.PagedResult50564100%
 
 
System.Linq.Dynamic.Core.PagedResult`110164100%
 
 
+System.Linq.Dynamic.Core.ParameterExpressionHelper30312100%
 
 
+System.Linq.Dynamic.Core.Parser.ConstantExpressionHelper1401429100%
 
100%
 
+System.Linq.Dynamic.Core.Parser.Constants30311100%
 
 
+System.Linq.Dynamic.Core.Parser.ExpressionHelper120512519996%
  
70.4%
  
+System.Linq.Dynamic.Core.Parser.ExpressionParser9961941190182483.6%
  
75.4%
  
+System.Linq.Dynamic.Core.Parser.ExpressionPromoter4835110194.1%
  
92.8%
  
+System.Linq.Dynamic.Core.Parser.KeywordsHelper4104167100%
 
75%
  
+System.Linq.Dynamic.Core.Parser.PredefinedTypesHelper4512579978.9%
  
50%
  
+System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodData30312100%
 
 
+System.Linq.Dynamic.Core.Parser.SupportedMethods.MethodFinder142614822995.9%
  
91%
  
+System.Linq.Dynamic.Core.Parser.TypeHelper1941821250691.5%
  
87%
  
+System.Linq.Dynamic.Core.ParsingConfig1201252100%
 
50%
  
System.Linq.Dynamic.Core.Res0000
 
 
-System.Linq.Dynamic.Core.Tokenizer.TextParser287128842399.6%
 
93.9%
  
+System.Linq.Dynamic.Core.Tokenizer.TextParser303330644799%
  
94.1%
  
System.Linq.Dynamic.Core.Tokenizer.Token40413100%
 
 
System.Linq.Dynamic.Core.TypeConverterFactory40436100%
 
 
System.Reflection.CustomIntrospectionExtensions30339100%
 
 
System.Reflection.CustomTypeBuilderExtensions30335100%
 
 
-
+ \ No newline at end of file diff --git a/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj b/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj index 9f3a3c72..3d1a3a54 100644 --- a/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj +++ b/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj @@ -25,10 +25,11 @@ false false en-us + {D3804228-91F4-4502-9595-39584E510000} + full - full True True $(MSBuildProjectDirectory)=/ @@ -48,10 +49,8 @@ - - 6.1.3 - + diff --git a/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj b/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj index 7ffb396c..971325cd 100644 --- a/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj +++ b/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj @@ -26,10 +26,11 @@ false false en-us + {D3804228-91F4-4502-9595-39584E510001} + full - full True True $(MSBuildProjectDirectory)=/ diff --git a/src/System.Linq.Dynamic.Core/DynamicClassFactory.cs b/src/System.Linq.Dynamic.Core/DynamicClassFactory.cs index 4a282173..94ea978e 100644 --- a/src/System.Linq.Dynamic.Core/DynamicClassFactory.cs +++ b/src/System.Linq.Dynamic.Core/DynamicClassFactory.cs @@ -62,10 +62,8 @@ public static class DynamicClassFactory private static int _index = -1; - /// - /// The AssemblyName - /// - public static string DynamicAssemblyName = "System.Linq.Dynamic.Core.DynamicClasses, Version=1.0.0.0"; + private static string DynamicAssemblyName = "System.Linq.Dynamic.Core.DynamicClasses, Version=1.0.0.0"; + private static string DynamicModuleName = "System.Linq.Dynamic.Core.DynamicClasses"; /// /// Initializes the class. @@ -75,7 +73,7 @@ static DynamicClassFactory() var assemblyName = new AssemblyName(DynamicAssemblyName); var assemblyBuilder = AssemblyBuilderFactory.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); - ModuleBuilder = assemblyBuilder.DefineDynamicModule("System.Linq.Dynamic.Core.DynamicClasses"); + ModuleBuilder = assemblyBuilder.DefineDynamicModule(DynamicModuleName); } /// diff --git a/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs b/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs index 2ca7b89f..50ac719d 100644 --- a/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs +++ b/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs @@ -11,7 +11,7 @@ namespace System.Linq.Dynamic.Core public static class DynamicExpressionParser { /// - /// *** Parses an expression into a LambdaExpression. + /// Parses an expression into a LambdaExpression. /// /// The Configuration for the parsing. /// if set to true then also create a constructor for all the parameters. Note that this doesn't work for Linq-to-Database entities. @@ -45,7 +45,7 @@ public static Expression> ParseLambda([CanBeNull] Parsing } /// - /// *** Parses an expression into a LambdaExpression. + /// Parses an expression into a LambdaExpression. /// /// The Configuration for the parsing. /// if set to true then also create a constructor for all the parameters. Note that this doesn't work for Linq-to-Database entities. diff --git a/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj b/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj index a1997865..c051f248 100644 --- a/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj +++ b/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj @@ -26,10 +26,11 @@ false false en-us + {D3804228-91F4-4502-9595-39584E510002} + full - full True True $(MSBuildProjectDirectory)=/ diff --git a/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj b/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj index 42bae680..d0c2b223 100644 --- a/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj +++ b/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj @@ -10,6 +10,7 @@ false false false + {D3804228-91F4-4502-9595-39584EF20000} diff --git a/test/System.Linq.Dynamic.Core.Tests/System.Linq.Dynamic.Core.Tests.csproj b/test/System.Linq.Dynamic.Core.Tests/System.Linq.Dynamic.Core.Tests.csproj index a9149096..f09d1ec2 100644 --- a/test/System.Linq.Dynamic.Core.Tests/System.Linq.Dynamic.Core.Tests.csproj +++ b/test/System.Linq.Dynamic.Core.Tests/System.Linq.Dynamic.Core.Tests.csproj @@ -1,72 +1,78 @@  - - Stef Heyenrath - netcoreapp1.1 - System.Linq.Dynamic.Core.Tests - $(PackageTargetFallback);dnxcore50;dotnet5.4;portable-net451+win8 - full - True - System.Linq.Dynamic.Core.snk - False - - - - - - - - - - - - - - - - 2.3.1 - - - 10.0.3 - - - 1.0.4 - - - 1.0.6 - - - 1.1.2 - - - 2.3.1 - - - - 1.1.1 - - - 1.1.1 - - - 1.1.1 - - - 1.1.1 - - - 4.3.0 - - - 4.3.0 - - - - - - - - - - $(DefineConstants);NETSTANDARD;EFCORE - + + Stef Heyenrath + netcoreapp1.1 + System.Linq.Dynamic.Core.Tests + full + True + System.Linq.Dynamic.Core.snk + False + {912FBF24-3CAE-4A50-B5EA-E525B9FAEC80} + + + + + + + + + + + + + + + + 10.0.3 + + + 1.0.4 + + + 1.0.6 + + + 2.3.1 + + + + + + + + + + + + + + + 4.3.0 + + + 4.3.0 + + + 1.1.1 + + + 1.1.1 + + + 1.1.1 + + + 1.1.1 + + + + + + + + + + + $(DefineConstants);NETSTANDARD;EFCORE + \ No newline at end of file