Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[release/v7.5] Make inherited protected internal instance members accessible in class scope.#25547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Show file tree
Hide file tree
Changes fromall 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
4 changes: 2 additions & 2 deletionssrc/System.Management.Automation/engine/CoreAdapter.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2835,7 +2835,7 @@ internal PropertyCacheEntry(PropertyInfo property)

// Get the public or protected getter
MethodInfopropertyGetter=property.GetGetMethod(true);
if(propertyGetter!=null&&(propertyGetter.IsPublic||propertyGetter.IsFamily))
if(propertyGetter!=null&&(propertyGetter.IsPublic||propertyGetter.IsFamily||propertyGetter.IsFamilyOrAssembly))
{
this.isStatic=propertyGetter.IsStatic;
// Delegate is initialized later to avoid jit if it's not called
Expand All@@ -2847,7 +2847,7 @@ internal PropertyCacheEntry(PropertyInfo property)

// Get the public or protected setter
MethodInfopropertySetter=property.GetSetMethod(true);
if(propertySetter!=null&&(propertySetter.IsPublic||propertySetter.IsFamily))
if(propertySetter!=null&&(propertySetter.IsPublic||propertySetter.IsFamily||propertySetter.IsFamilyOrAssembly))
{
this.isStatic=propertySetter.IsStatic;
}
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5297,7 +5297,8 @@ public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, Dy
var propertyAccessor = adapterData.member as PropertyInfo;
if (propertyAccessor != null)
{
if (propertyAccessor.GetMethod.IsFamily &&
var propertyGetter = propertyAccessor.GetMethod;
if ((propertyGetter.IsFamily || propertyGetter.IsFamilyOrAssembly) &&
(_classScope == null || !_classScope.IsSubclassOf(propertyAccessor.DeclaringType)))
{
return GenerateGetPropertyException(restrictions).WriteToDebugLog(this);
Expand DownExpand Up@@ -5757,8 +5758,8 @@ internal PSMemberInfo GetPSMemberInfo(DynamicMetaObject target,
var getMethod = propertyInfo.GetGetMethod(nonPublic: true);
var setMethod = propertyInfo.GetSetMethod(nonPublic: true);

if ((getMethod == null || getMethod.IsFamily || getMethod.IsPublic) &&
(setMethod == null || setMethod.IsFamily || setMethod.IsPublic))
if ((getMethod == null || getMethod.IsPublic || getMethod.IsFamily || getMethod.IsFamilyOrAssembly) &&
(setMethod == null || setMethod.IsPublic || setMethod.IsFamily || setMethod.IsFamilyOrAssembly))
{
memberInfo = new PSProperty(this.Name, PSObject.DotNetInstanceAdapter, target.Value, new DotNetAdapter.PropertyCacheEntry(propertyInfo));
}
Expand All@@ -5768,15 +5769,15 @@ internal PSMemberInfo GetPSMemberInfo(DynamicMetaObject target,
var fieldInfo = member as FieldInfo;
if (fieldInfo != null)
{
if (fieldInfo.IsFamily)
if (fieldInfo.IsFamily || fieldInfo.IsFamilyOrAssembly)
{
memberInfo = new PSProperty(this.Name, PSObject.DotNetInstanceAdapter, target.Value, new DotNetAdapter.PropertyCacheEntry(fieldInfo));
}
}
else
{
var methodInfo = member as MethodInfo;
if (methodInfo != null && (methodInfo.IsPublic || methodInfo.IsFamily))
if (methodInfo != null && (methodInfo.IsPublic || methodInfo.IsFamily || methodInfo.IsFamilyOrAssembly))
{
candidateMethods ??= new List<MethodBase>();

Expand DownExpand Up@@ -6291,7 +6292,8 @@ public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, Dy
var targetExpr = _static ? null : PSGetMemberBinder.GetTargetExpr(target, data.member.DeclaringType);
if (propertyInfo != null)
{
if (propertyInfo.SetMethod.IsFamily &&
var propertySetter = propertyInfo.SetMethod;
if ((propertySetter.IsFamily || propertySetter.IsFamilyOrAssembly) &&
(_classScope == null || !_classScope.IsSubclassOf(propertyInfo.DeclaringType)))
{
return GeneratePropertyAssignmentException(restrictions).WriteToDebugLog(this);
Expand DownExpand Up@@ -7826,7 +7828,7 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target,
? BindingRestrictions.GetTypeRestriction(target.Expression, target.Value.GetType())
: target.PSGetTypeRestriction();
restrictions = args.Aggregate(restrictions, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction()));
var newConstructors = DotNetAdapter.GetMethodInformationArray(ctors.Where(static c => c.IsPublic || c.IsFamily).ToArray());
var newConstructors = DotNetAdapter.GetMethodInformationArray(ctors.Where(static c => c.IsPublic || c.IsFamily || c.IsFamilyOrAssembly).ToArray());
return PSInvokeMemberBinder.InvokeDotNetMethod(_callInfo, "new", _constraints, PSInvokeMemberBinder.MethodInvocationType.BaseCtor,
target, args, restrictions, newConstructors, typeof(MethodException));
}
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -672,3 +672,209 @@ Describe 'Base type has abstract properties' -Tags "CI" {
$failure.Exception.Message| Should-BeLike"*'get_Exists'*"
}
}

Describe'Classes inheritance with protected and protected internal members in base class'-Tags'CI' {

BeforeAll {
Set-StrictMode-Version3
$c1DefinitionProtectedInternal=@'
public class C1ProtectedInternal
{
protected internal string InstanceField = "C1_InstanceField";
protected internal string InstanceProperty { get; set; } = "C1_InstanceProperty";
protected internal string InstanceMethod() { return "C1_InstanceMethod"; }
protected internal virtual string VirtualProperty1 { get; set; } = "C1_VirtualProperty1";
protected internal virtual string VirtualProperty2 { get; set; } = "C1_VirtualProperty2";
protected internal virtual string VirtualMethod1() { return "C1_VirtualMethod1"; }
protected internal virtual string VirtualMethod2() { return "C1_VirtualMethod2"; }
public string CtorUsed { get; set; }
public C1ProtectedInternal() { CtorUsed = "default ctor"; }
protected internal C1ProtectedInternal(string p1) { CtorUsed = "C1_ctor_1args:" + p1; }
}
'@
$c2DefinitionProtectedInternal=@'
class C2ProtectedInternal : C1ProtectedInternal {
C2ProtectedInternal() : base() { $this.VirtualProperty2 = 'C2_VirtualProperty2' }
C2ProtectedInternal([string]$p1) : base($p1) { $this.VirtualProperty2 = 'C2_VirtualProperty2' }
[string]GetInstanceField() { return $this.InstanceField }
[string]SetInstanceField([string]$value) { $this.InstanceField = $value; return $this.InstanceField }
[string]GetInstanceProperty() { return $this.InstanceProperty }
[string]SetInstanceProperty([string]$value) { $this.InstanceProperty = $value; return $this.InstanceProperty }
[string]CallInstanceMethod() { return $this.InstanceMethod() }
[string]GetVirtualProperty1() { return $this.VirtualProperty1 }
[string]SetVirtualProperty1([string]$value) { $this.VirtualProperty1 = $value; return $this.VirtualProperty1 }
[string]CallVirtualMethod1() { return $this.VirtualMethod1() }
[string]$VirtualProperty2
[string]VirtualMethod2() { return 'C2_VirtualMethod2' }
# Note: Overriding a virtual property in a derived PowerShell class prevents access to the
# base property via simple typecast ([base]$this).VirtualProperty2.
[string]GetVirtualProperty2() { return $this.VirtualProperty2 }
[string]SetVirtualProperty2([string]$value) { $this.VirtualProperty2 = $value; return $this.VirtualProperty2 }
[string]CallVirtualMethod2Base() { return ([C1ProtectedInternal]$this).VirtualMethod2() }
[string]CallVirtualMethod2Derived() { return $this.VirtualMethod2() }
[string]GetInstanceMemberDynamic([string]$name) { return $this.$name }
[string]SetInstanceMemberDynamic([string]$name, [string]$value) { $this.$name = $value; return $this.$name }
[string]CallInstanceMemberDynamic([string]$name) { return $this.$name() }
}
[C2ProtectedInternal]
'@

Add-Type-TypeDefinition$c1DefinitionProtectedInternal
Add-Type-TypeDefinition (($c1DefinitionProtectedInternal-creplace'C1ProtectedInternal','C1Protected')-creplace'protected internal','protected')

$testCases=@(
@{accessType='protected';derivedType=Invoke-Expression ($c2DefinitionProtectedInternal-creplace'ProtectedInternal','Protected') }
@{accessType='protected internal';derivedType=Invoke-Expression$c2DefinitionProtectedInternal }
)
}

AfterAll {
Set-StrictMode-Off
}

Context'Derived class can access instance base class members' {

It'can call protected internal .NET method Object.MemberwiseClone()' {
classCNetMethod {
[string]$Foo
[object]CloneIt() {return$this.MemberwiseClone() }
}
$c1= [CNetMethod]::new()
$c1.Foo='bar'
$c2=$c1.CloneIt()
$c2.Foo| Should-Be'bar'
}

It'can call <accessType> base ctor'-TestCases$testCases {
param($derivedType)
$derivedType::new('foo').CtorUsed| Should-Be'C1_ctor_1args:foo'
}

It'can access <accessType> base field'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.GetInstanceField()| Should-Be'C1_InstanceField'
$c2.SetInstanceField('foo_InstanceField')| Should-Be'foo_InstanceField'
}

It'can access <accessType> base property'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.GetInstanceProperty()| Should-Be'C1_InstanceProperty'
$c2.SetInstanceProperty('foo_InstanceProperty')| Should-Be'foo_InstanceProperty'
}

It'can call <accessType> base method'-TestCases$testCases {
param($derivedType)
$derivedType::new().CallInstanceMethod()| Should-Be'C1_InstanceMethod'
}

It'can access <accessType> virtual base property'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.GetVirtualProperty1()| Should-Be'C1_VirtualProperty1'
$c2.SetVirtualProperty1('foo_VirtualProperty1')| Should-Be'foo_VirtualProperty1'
}

It'can call <accessType> virtual base method'-TestCases$testCases {
param($derivedType)
$derivedType::new().CallVirtualMethod1()| Should-Be'C1_VirtualMethod1'
}
}

Context'Derived class can override virtual base class members' {

It'can override <accessType> virtual base property'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.GetVirtualProperty2()| Should-Be'C2_VirtualProperty2'
$c2.SetVirtualProperty2('foo_VirtualProperty2')| Should-Be'foo_VirtualProperty2'
}

It'can override <accessType> virtual base method'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.CallVirtualMethod2Base()| Should-Be'C1_VirtualMethod2'
$c2.CallVirtualMethod2Derived()| Should-Be'C2_VirtualMethod2'
}
}

Context'Derived class can access instance base class members dynamically' {

It'can access <accessType> base fields and properties'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.GetInstanceMemberDynamic('InstanceField')| Should-Be'C1_InstanceField'
$c2.GetInstanceMemberDynamic('InstanceProperty')| Should-Be'C1_InstanceProperty'
$c2.GetInstanceMemberDynamic('VirtualProperty1')| Should-Be'C1_VirtualProperty1'
$c2.SetInstanceMemberDynamic('InstanceField','foo1')| Should-Be'foo1'
$c2.SetInstanceMemberDynamic('InstanceProperty','foo2')| Should-Be'foo2'
$c2.SetInstanceMemberDynamic('VirtualProperty1','foo3')| Should-Be'foo3'
}

It'can call <accessType> base methods'-TestCases$testCases {
param($derivedType)
$c2=$derivedType::new()
$c2.CallInstanceMemberDynamic('InstanceMethod')| Should-Be'C1_InstanceMethod'
$c2.CallInstanceMemberDynamic('VirtualMethod1')| Should-Be'C1_VirtualMethod1'
}
}

Context'Base class members are not accessible outside class scope' {

BeforeAll {
$instanceTest= {
$c2=$derivedType::new()
{$null=$c2.InstanceField }| Should-Throw-ErrorId'PropertyNotFoundStrict'
{$null=$c2.InstanceProperty }| Should-Throw-ErrorId'PropertyNotFoundStrict'
{$null=$c2.VirtualProperty1 }| Should-Throw-ErrorId'PropertyNotFoundStrict'
{$c2.InstanceField='foo' }| Should-Throw-ErrorId'PropertyAssignmentException'
{$c2.InstanceProperty='foo' }| Should-Throw-ErrorId'PropertyAssignmentException'
{$c2.VirtualProperty1='foo' }| Should-Throw-ErrorId'PropertyAssignmentException'
{$derivedType::new().InstanceMethod() }| Should-Throw-ErrorId'MethodNotFound'
{$derivedType::new().VirtualMethod1() }| Should-Throw-ErrorId'MethodNotFound'
foreach ($namein@('InstanceField','InstanceProperty','VirtualProperty1')) {
{$null=$c2.$name }| Should-Throw-ErrorId'PropertyNotFoundStrict'
{$c2.$name='foo' }| Should-Throw-ErrorId'PropertyAssignmentException'
}
foreach ($namein@('InstanceMethod','VirtualMethod1')) {
{$c2.$name() }| Should-Throw-ErrorId'MethodNotFound'
}
}
$c3UnrelatedType=Invoke-Expression@"
class C3Unrelated {
[void]RunInstanceTest([type]`$derivedType) {$instanceTest }
}
[C3Unrelated]
"@
$negativeTestCases=$testCases.ForEach({
$item=$_.Clone()
$item['scopeType']='null scope'
$item['classScope']=$null
$item
$item=$_.Clone()
$item['scopeType']='unrelated class scope'
$item['classScope']=$c3UnrelatedType
$item
})
}

It'cannot access <accessType> instance base members in <scopeType>'-TestCases$negativeTestCases {
param($derivedType,$classScope)
if ($null-eq$classScope) {
$instanceTest.Invoke()
}
else {
$c3=$classScope::new()
$c3.RunInstanceTest($derivedType)
}
}
}
}
Loading

[8]ページ先頭

©2009-2025 Movatter.jp