Conditionally mark getter/setter implementations virtual in generated classes (#8303)
When implementing interfaces, PowerShell incorrectly produces non-virtual get/set methods for interface-defined properties. This commit adds a lookup method for interface-defined properties and marks get/set methods for properties with matching signatures virtual.
This commit is contained in:
parent
6e523f21eb
commit
950377faab
|
@ -434,6 +434,19 @@ namespace System.Management.Automation.Language
|
|||
return baseClass ?? typeof(object);
|
||||
}
|
||||
|
||||
private bool ShouldImplementProperty(string name, Type type)
|
||||
{
|
||||
foreach (var interfaceType in _typeBuilder.GetInterfaces())
|
||||
{
|
||||
if (interfaceType.GetProperty(name, type) != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void DefineMembers()
|
||||
{
|
||||
// If user didn't provide any instance ctors or static ctor we will generate default ctor or static ctor respectively.
|
||||
|
@ -576,6 +589,11 @@ namespace System.Management.Automation.Language
|
|||
// The property set and property get methods require a special set of attributes.
|
||||
var getSetAttributes = Reflection.MethodAttributes.SpecialName | Reflection.MethodAttributes.HideBySig;
|
||||
getSetAttributes |= propertyMemberAst.IsPublic ? Reflection.MethodAttributes.Public : Reflection.MethodAttributes.Private;
|
||||
if (ShouldImplementProperty(propertyMemberAst.Name, type))
|
||||
{
|
||||
getSetAttributes |= Reflection.MethodAttributes.Virtual;
|
||||
}
|
||||
|
||||
if (propertyMemberAst.IsStatic)
|
||||
{
|
||||
backingFieldAttributes |= FieldAttributes.Static;
|
||||
|
|
|
@ -63,6 +63,14 @@ Describe 'Classes inheritance syntax' -Tags "CI" {
|
|||
[MyComparable].GetInterface("System.IComparable") | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'can implement .NET interface properties' {
|
||||
Add-Type -TypeDefinition 'public interface InterfaceWithProperty { int Integer { get; set; } }'
|
||||
$C1 = Invoke-Expression 'class ClassWithInterfaceProperty : InterfaceWithProperty { [int]$Integer } [ClassWithInterfaceProperty]::new()'
|
||||
$getter = $C1.GetType().GetMember('get_Integer')
|
||||
$getter.ReturnType.FullName | Should -Be System.Int32
|
||||
$getter.Attributes -band [System.Reflection.MethodAttributes]::Virtual |Should -Be ([System.Reflection.MethodAttributes]::Virtual)
|
||||
}
|
||||
|
||||
It 'allows use of defined later type as a property type' {
|
||||
class A { static [B]$b }
|
||||
class B : A {}
|
||||
|
|
Loading…
Reference in a new issue