Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/System.Management.Automation/engine/parser/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ internal static class CachedReflectionInfo
new Type[] { typeof(int), typeof(IEqualityComparer) },
null);

internal static readonly MethodInfo ByRefOps_GetByRefPropertyValue =
typeof(ByRefOps).GetMethod(nameof(ByRefOps.GetByRefPropertyValue), StaticFlags);

internal static readonly MethodInfo HashtableOps_Add =
typeof(HashtableOps).GetMethod(nameof(HashtableOps.Add), StaticFlags);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5277,7 +5277,17 @@ public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, Dy
return GenerateGetPropertyException(restrictions).WriteToDebugLog(this);
}

expr = Expression.Property(targetExpr, propertyAccessor);
if (propertyAccessor.PropertyType.IsByRef)
{
expr = Expression.Call(
CachedReflectionInfo.ByRefOps_GetByRefPropertyValue,
targetExpr,
Expression.Constant(propertyAccessor));
}
else
{
expr = Expression.Property(targetExpr, propertyAccessor);
}
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,17 @@ internal ScriptBlock GetScriptBlock(ExecutionContext context, bool isFilter)
}
}

internal static class ByRefOps
{
/// <summary>
/// There is no way to directly work with ByRef type in the expression tree, so we turn to reflection in this case.
/// </summary>
internal static object GetByRefPropertyValue(object target, PropertyInfo property)
{
return property.GetValue(target);
}
}

internal static class HashtableOps
{
internal static void AddKeyValuePair(IDictionary hashtable, object key, object value, IScriptExtent errorExtent)
Expand Down
18 changes: 18 additions & 0 deletions test/powershell/Language/Scripting/Adapter.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,21 @@ Describe "Interface static members" -Tags "CI" {
$obj.GetId() | Should -Be 100
}
}

Describe "ByRef property" -Tags "CI" {

It "Get value from ByRef property" {
$list = [System.Collections.Generic.LinkedList[int]]::new()
$node = $list.AddLast(1)

## Get value through language binder.
$node.ValueRef | Should -Be 1

## Get value through .NET adapter.
$property = $node.PSObject.Properties["ValueRef"]
$property.IsSettable | Should -BeFalse
$property.IsGettable | Should -BeTrue
$property.TypeNameOfValue | Should -BeExactly 'System.Int32&'
$property.Value | Should -Be 1
}
}