diff --git a/src/System.Management.Automation/engine/parser/PSType.cs b/src/System.Management.Automation/engine/parser/PSType.cs index a495ea5f5aa..7a567f37a01 100644 --- a/src/System.Management.Automation/engine/parser/PSType.cs +++ b/src/System.Management.Automation/engine/parser/PSType.cs @@ -266,6 +266,7 @@ private class DefineTypeHelper internal readonly TypeBuilder _staticHelpersTypeBuilder; private readonly Dictionary _definedProperties; private readonly Dictionary>> _definedMethods; + private HashSet> _interfaceProperties; internal readonly List<(string fieldName, IParameterMetadataProvider bodyAst, bool isStatic)> _fieldsToInitForMemberFunctions; private bool _baseClassHasDefaultCtor; @@ -436,15 +437,33 @@ private Type GetBaseTypes(Parser parser, TypeDefinitionAst typeDefinitionAst, ou private bool ShouldImplementProperty(string name, Type type) { - foreach (var interfaceType in _typeBuilder.GetInterfaces()) + if (_interfaceProperties == null) { - if (interfaceType.GetProperty(name, type) != null) + _interfaceProperties = new HashSet>(); + var allInterfaces = new HashSet(); + + // TypeBuilder.GetInterfaces() returns only the interfaces that was explicitly passed to its constructor. + // During compilation the interface hierarchy is flattened, so we only need to resolve one level of ancestral interfaces. + foreach (var interfaceType in _typeBuilder.GetInterfaces()) + { + foreach (var parentInterface in interfaceType.GetInterfaces()) + { + allInterfaces.Add(parentInterface); + } + + allInterfaces.Add(interfaceType); + } + + foreach (var interfaceType in allInterfaces) { - return true; + foreach (var property in interfaceType.GetProperties()) + { + _interfaceProperties.Add(Tuple.Create(property.Name, property.PropertyType)); + } } } - return false; + return _interfaceProperties.Contains(Tuple.Create(name, type)); } public void DefineMembers() diff --git a/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 b/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 index caebc7181a2..72f9ece53b7 100644 --- a/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 +++ b/test/powershell/Language/Classes/scripting.Classes.inheritance.tests.ps1 @@ -71,6 +71,15 @@ Describe 'Classes inheritance syntax' -Tags "CI" { $getter.Attributes -band [System.Reflection.MethodAttributes]::Virtual |Should -Be ([System.Reflection.MethodAttributes]::Virtual) } + It 'can implement inherited .NET interface properties' { + Add-Type -TypeDefinition 'public interface IParent { int ParentInteger { get; set; } } + public interface IChild : IParent { int ChildInteger { get; set; } }' + $C1 = Invoke-Expression 'class ClassWithInheritedInterfaces : IChild { [int]$ParentInteger; [int]$ChildInteger } [ClassWithInheritedInterfaces]' + $getter = $C1.GetMember('get_ParentInteger') + $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 {}