Unwrap 'ValueFromRemainingArguments' if the single element is a collection (#5109)
Unwrapping of 'ValueFromRemainingArguments' was being performed only for 'object[]' arrays (which covers the most common PowerShell binding scenarios) but could be skipped if a collection of any other type were passed to the parameter. This change unwraps 'ValueFromRemainingArguments' if the single element is a collection.
This commit is contained in:
parent
5913069e58
commit
1c469aaa22
|
@ -1690,8 +1690,8 @@ namespace System.Management.Automation
|
||||||
// Set-ClusterOwnerNode -Owners foo,bar
|
// Set-ClusterOwnerNode -Owners foo,bar
|
||||||
// Set-ClusterOwnerNode foo bar
|
// Set-ClusterOwnerNode foo bar
|
||||||
// Set-ClusterOwnerNode foo,bar
|
// Set-ClusterOwnerNode foo,bar
|
||||||
// we unwrap our List, but only if there is a single argument of type object[].
|
// we unwrap our List, but only if there is a single argument which is a collection.
|
||||||
if (valueFromRemainingArguments.Count == 1 && valueFromRemainingArguments[0] is object[])
|
if (valueFromRemainingArguments.Count == 1 && LanguagePrimitives.IsObjectEnumerable(valueFromRemainingArguments[0]))
|
||||||
{
|
{
|
||||||
cpi.SetArgumentValue(UnboundArguments[0].ArgumentExtent, valueFromRemainingArguments[0]);
|
cpi.SetArgumentValue(UnboundArguments[0].ArgumentExtent, valueFromRemainingArguments[0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,10 +440,24 @@ namespace System.Management.Automation
|
||||||
|
|
||||||
internal static bool IsTypeEnumerable(Type type)
|
internal static bool IsTypeEnumerable(Type type)
|
||||||
{
|
{
|
||||||
|
if (type == null) { return false; }
|
||||||
GetEnumerableDelegate getEnumerable = GetOrCalculateEnumerable(type);
|
GetEnumerableDelegate getEnumerable = GetOrCalculateEnumerable(type);
|
||||||
return (getEnumerable != LanguagePrimitives.ReturnNullEnumerable);
|
return (getEnumerable != LanguagePrimitives.ReturnNullEnumerable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns True if the language considers obj to be IEnumerable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">
|
||||||
|
/// IEnumerable or IEnumerable-like object
|
||||||
|
/// </param>
|
||||||
|
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj", Justification = "Since V1 code is already shipped, excluding this message.")]
|
||||||
|
public static bool IsObjectEnumerable(object obj)
|
||||||
|
{
|
||||||
|
return IsTypeEnumerable(PSObject.Base(obj)?.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the IEnumerable of obj or null if the language does not consider obj to be IEnumerable
|
/// Retrieves the IEnumerable of obj or null if the language does not consider obj to be IEnumerable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -453,26 +467,9 @@ namespace System.Management.Automation
|
||||||
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj", Justification = "Since V1 code is already shipped, excluding this message.")]
|
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj", Justification = "Since V1 code is already shipped, excluding this message.")]
|
||||||
public static IEnumerable GetEnumerable(object obj)
|
public static IEnumerable GetEnumerable(object obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
obj = PSObject.Base(obj);
|
||||||
{
|
if (obj == null) { return null; }
|
||||||
return null;
|
GetEnumerableDelegate getEnumerable = GetOrCalculateEnumerable(obj.GetType());
|
||||||
}
|
|
||||||
|
|
||||||
Type objectType = obj.GetType();
|
|
||||||
|
|
||||||
// if the object passed is an PSObject,
|
|
||||||
// look at the base object. Notice that, if the
|
|
||||||
// object has been serialized, the base object
|
|
||||||
// will be there as an ArrayList if the original
|
|
||||||
// object was IEnumerable
|
|
||||||
if (objectType == typeof(PSObject))
|
|
||||||
{
|
|
||||||
PSObject mshObj = (PSObject)obj;
|
|
||||||
obj = mshObj.BaseObject;
|
|
||||||
objectType = obj.GetType();
|
|
||||||
}
|
|
||||||
|
|
||||||
GetEnumerableDelegate getEnumerable = GetOrCalculateEnumerable(objectType);
|
|
||||||
return getEnumerable(obj);
|
return getEnumerable(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -422,5 +422,25 @@
|
||||||
$result.Value[1] | Should Be 2
|
$result.Value[1] | Should Be 2
|
||||||
$result.Value[2] | Should Be 3
|
$result.Value[2] | Should Be 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It "Binds properly when collections of type other than object[] are used on an advanced function" {
|
||||||
|
$list = [Collections.Generic.List[int]](1..3)
|
||||||
|
$result = Test-BindingFunction $list
|
||||||
|
|
||||||
|
$result.ArgumentCount | Should Be 3
|
||||||
|
$result.Value[0] | Should Be 1
|
||||||
|
$result.Value[1] | Should Be 2
|
||||||
|
$result.Value[2] | Should Be 3
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Binds properly when collections of type other than object[] are used on a cmdlet" {
|
||||||
|
$list = [Collections.Generic.List[int]](1..3)
|
||||||
|
$result = Test-BindingCmdlet $list
|
||||||
|
|
||||||
|
$result.ArgumentCount | Should Be 3
|
||||||
|
$result.Value[0] | Should Be 1
|
||||||
|
$result.Value[1] | Should Be 2
|
||||||
|
$result.Value[2] | Should Be 3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue