helpers/Convert-RetrievalIncludeExpression.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#Requires -Version 3.0

<#
  Convert-RetrievalIncludeExpression.ps1
 
  Copyright (c) 2017 karamem0
 
  This software is released under the MIT License.
  https://github.com/karamem0/SPClient/blob/master/LICENSE
#>


function Convert-RetrievalIncludeExpression {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]
        $InputString,
        [Parameter(Mandatory = $true)]
        [System.Linq.Expressions.Expression]
        $Expression
    )

    process {
        if (-not $InputString.StartsWith('Include(')) {
            throw "Cannot convert expression because 'InputString' parameter does not start with 'Include('."
        }
        if (-not $InputString.EndsWith(')')) {
            throw "Cannot convert expression because 'InputString' parameter does not end with ')'."
        }
        $InputString = $InputString.Substring(8, $InputString.Length - 9)
        $ItemType = $Expression.Type.BaseType.GenericTypeArguments[0]
        $FuncType = [type]'System.Func`2' | &{ process { $_.MakeGenericType($ItemType, [object]) } }
        $ExprType = [type]'System.Linq.Expressions.Expression`1' | &{ process { $_.MakeGenericType($FuncType) } }
        $ListType = [type]'System.Collections.Generic.List`1' | &{ process { $_.MakeGenericType($ExprType) } }
        $ParamExpr = [System.Linq.Expressions.Expression]::Parameter($ItemType, $ItemType.Name)
        $LambdaExprs = New-Object $ListType
        $Splits = Split-RetrievalExpressionString -InputString $InputString -Separator ','
        if ($Splits -ne '*') {
            foreach ($Split in $Splits) {
                $PropExpr = Convert-RetrievalMemberAccessExpression -InputString $Split -Expression $ParamExpr
                $CastExpr = [System.Linq.Expressions.Expression]::Convert($PropExpr, [object])
                $LambdaExpr = [System.Linq.Expressions.Expression]::Lambda($FuncType, $CastExpr, $ParamExpr)
                $LambdaExprs.Add($LambdaExpr)
            }
        }
        $ExtType = [Microsoft.SharePoint.Client.ClientObjectQueryableExtension]
        $ArrayExpr = [System.Linq.Expressions.Expression]::NewArrayInit($ExprType, $LambdaExprs.ToArray())
        if ($Splits -contains '*') {
            $IncludeExpr = [System.Linq.Expressions.Expression]::Call( `
                $ExtType.GetMethod('IncludeWithDefaultProperties').MakeGenericMethod($ItemType), `
                [System.Linq.Expressions.Expression[]]@($Expression, $ArrayExpr)
            )
            Write-Output $IncludeExpr
        } else {
            $IncludeExpr = [System.Linq.Expressions.Expression]::Call( `
                $ExtType.GetMethod('Include').MakeGenericMethod($ItemType), `
                [System.Linq.Expressions.Expression[]]@($Expression, $ArrayExpr)
            )
            Write-Output $IncludeExpr
        }
    }

}