11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT License.
33
4+ using System . Buffers ;
45using System . Collections ;
56using System . Collections . Concurrent ;
67using System . Collections . Generic ;
@@ -6533,6 +6534,14 @@ public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, Dynam
65336534
65346535 internal sealed class PSInvokeMemberBinder : InvokeMemberBinder
65356536 {
6537+ private const string WhereMagicMethodName = "Where" ;
6538+ private const string WhereMagicMethodPSName = $ "PS{ WhereMagicMethodName } ";
6539+ private const string ForeachMagicMethodName = "Foreach" ;
6540+ private const string ForeachMagicMethodPSName = $ "PS{ ForeachMagicMethodName } ";
6541+
6542+ private static readonly SearchValues < string > s_whereSearchValues = SearchValues . Create ( [ WhereMagicMethodName , WhereMagicMethodPSName ] , StringComparison . OrdinalIgnoreCase ) ;
6543+ private static readonly SearchValues < string > s_foreachSearchValues = SearchValues . Create ( [ ForeachMagicMethodName , ForeachMagicMethodPSName ] , StringComparison . OrdinalIgnoreCase ) ;
6544+
65366545 internal enum MethodInvocationType
65376546 {
65386547 Ordinary ,
@@ -6681,12 +6690,14 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target,
66816690 . WriteToDebugLog ( this ) ;
66826691 BindingRestrictions argRestrictions = args . Aggregate ( BindingRestrictions . Empty , static ( current , arg ) => current . Merge ( arg . PSGetMethodArgumentRestriction ( ) ) ) ;
66836692
6684- if ( string . Equals ( Name , "Where" , StringComparison . OrdinalIgnoreCase ) )
6693+ if ( s_whereSearchValues . Contains ( Name ) )
66856694 {
66866695 return InvokeWhereOnCollection ( emptyEnumerator , args , argRestrictions ) . WriteToDebugLog ( this ) ;
66876696 }
66886697
6689- if ( string . Equals ( Name , "ForEach" , StringComparison . OrdinalIgnoreCase ) )
6698+ if ( s_foreachSearchValues . Contains ( Name ) )
6699+ // We need to pass the empty enumerator to the ForEach operator, so that it can return an empty collection.
6700+ // The ForEach operator will not be able to call the script block if the enumerator is empty.
66906701 {
66916702 return InvokeForEachOnCollection ( emptyEnumerator , args , argRestrictions ) . WriteToDebugLog ( this ) ;
66926703 }
@@ -6866,12 +6877,12 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target,
68666877 if ( ! _static && ! _nonEnumerating && target . Value != AutomationNull . Value )
68676878 {
68686879 // Invoking Where and ForEach operators on collections.
6869- if ( string . Equals ( Name , "Where" , StringComparison . OrdinalIgnoreCase ) )
6880+ if ( s_whereSearchValues . Contains ( Name ) )
68706881 {
68716882 return InvokeWhereOnCollection ( target , args , restrictions ) . WriteToDebugLog ( this ) ;
68726883 }
68736884
6874- if ( string . Equals ( Name , "ForEach" , StringComparison . OrdinalIgnoreCase ) )
6885+ if ( s_foreachSearchValues . Contains ( Name ) )
68756886 {
68766887 return InvokeForEachOnCollection ( target , args , restrictions ) . WriteToDebugLog ( this ) ;
68776888 }
@@ -7490,7 +7501,7 @@ internal static object InvokeAdaptedMember(object obj, string methodName, object
74907501 // As a last resort, we invoke 'Where' and 'ForEach' operators on singletons like
74917502 // ([pscustomobject]@{ foo = 'bar' }).Foreach({$_})
74927503 // ([pscustomobject]@{ foo = 'bar' }).Where({1})
7493- if ( string . Equals ( methodName , "Where" , StringComparison . OrdinalIgnoreCase ) )
7504+ if ( s_whereSearchValues . Contains ( methodName ) )
74947505 {
74957506 var enumerator = ( new object [ ] { obj } ) . GetEnumerator ( ) ;
74967507 switch ( args . Length )
@@ -7506,7 +7517,7 @@ internal static object InvokeAdaptedMember(object obj, string methodName, object
75067517 }
75077518 }
75087519
7509- if ( string . Equals ( methodName , "Foreach" , StringComparison . OrdinalIgnoreCase ) )
7520+ if ( s_foreachSearchValues . Contains ( methodName ) )
75107521 {
75117522 var enumerator = ( new object [ ] { obj } ) . GetEnumerator ( ) ;
75127523 object [ ] argsToPass ;
0 commit comments