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

Commita07f00c

Browse files
committed
base accessors were not exposed to Python because .NET PropertyInfo GetMethod would not return base non-overriden accessor for a partially overriden property
because of that when constructing PropertyObject we scan base classes to find base accessor (if any)this might have performance implications due to replacement of PropertyInfo.GetValue with getter.Invoke (not tested)fixes#1455
1 parent8d6a918 commita07f00c

File tree

3 files changed

+103
-9
lines changed

3 files changed

+103
-9
lines changed

‎src/embed_tests/Inheritance.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ public void BaseClearIsCalled()
119119
scope.Set("exn",null);
120120
Assert.AreEqual(1,msg.Refcount);
121121
}
122+
123+
// https://github.com/pythonnet/pythonnet/issues/1455
124+
[Test]
125+
publicvoidPropertyAccessorOverridden()
126+
{
127+
usingvarderived=newPropertyAccessorDerived().ToPython();
128+
derived.SetAttr(nameof(PropertyAccessorDerived.VirtualProp),"hi".ToPython());
129+
Assert.AreEqual("HI",derived.GetAttr(nameof(PropertyAccessorDerived.VirtualProp)).As<string>());
130+
}
122131
}
123132

124133
classExtraBaseTypeProvider:IPythonBaseTypeProvider
@@ -192,6 +201,18 @@ public int XProp
192201
}
193202
}
194203

204+
publicclassPropertyAccessorBase
205+
{
206+
publicvirtualstringVirtualProp{get;set;}
207+
}
208+
209+
publicclassPropertyAccessorIntermediate:PropertyAccessorBase{}
210+
211+
publicclassPropertyAccessorDerived:PropertyAccessorIntermediate
212+
{
213+
publicoverridestringVirtualProp{set=>base.VirtualProp=value.ToUpperInvariant();}
214+
}
215+
195216
publicclassContainerClass
196217
{
197218
publicvoidBaseMethod(){}

‎src/runtime/ReflectionUtil.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
namespacePython.Runtime;
2+
3+
usingSystem;
4+
usingSystem.Reflection;
5+
6+
staticclassReflectionUtil
7+
{
8+
publicstaticMethodInfo?GetBaseGetMethod(thisPropertyInfoproperty,boolnonPublic)
9+
{
10+
if(propertyisnull)thrownewArgumentNullException(nameof(property));
11+
12+
TypebaseType=property.DeclaringType.BaseType;
13+
BindingFlagsbindingFlags=property.GetBindingFlags();
14+
15+
while(baseTypeis notnull)
16+
{
17+
varbaseProperty=baseType.GetProperty(property.Name,bindingFlags|BindingFlags.DeclaredOnly);
18+
varaccessor=baseProperty?.GetGetMethod(nonPublic);
19+
if(accessoris notnull)
20+
returnaccessor;
21+
22+
baseType=baseType.BaseType;
23+
}
24+
25+
returnnull;
26+
}
27+
28+
publicstaticMethodInfo?GetBaseSetMethod(thisPropertyInfoproperty,boolnonPublic)
29+
{
30+
if(propertyisnull)thrownewArgumentNullException(nameof(property));
31+
32+
TypebaseType=property.DeclaringType.BaseType;
33+
BindingFlagsbindingFlags=property.GetBindingFlags();
34+
35+
while(baseTypeis notnull)
36+
{
37+
varbaseProperty=baseType.GetProperty(property.Name,bindingFlags|BindingFlags.DeclaredOnly);
38+
varaccessor=baseProperty?.GetSetMethod(nonPublic);
39+
if(accessoris notnull)
40+
returnaccessor;
41+
42+
baseType=baseType.BaseType;
43+
}
44+
45+
returnnull;
46+
}
47+
48+
publicstaticBindingFlagsGetBindingFlags(thisPropertyInfoproperty)
49+
{
50+
varaccessor=property.GetMethod??property.SetMethod;
51+
BindingFlagsflags=default;
52+
flags|=accessor.IsStatic?BindingFlags.Static:BindingFlags.Instance;
53+
flags|=accessor.IsPublic?BindingFlags.Public:BindingFlags.NonPublic;
54+
returnflags;
55+
}
56+
}

‎src/runtime/propertyobject.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
usingSystem;
22
usingSystem.Reflection;
3+
usingSystem.Runtime.Serialization;
34

45
namespacePython.Runtime
56
{
@@ -8,17 +9,25 @@ namespace Python.Runtime
89
/// Implements a Python descriptor type that manages CLR properties.
910
/// </summary>
1011
[Serializable]
11-
internalclassPropertyObject:ExtensionType
12+
internalclassPropertyObject:ExtensionType,IDeserializationCallback
1213
{
1314
internalMaybeMemberInfo<PropertyInfo>info;
14-
privateMaybeMethodInfogetter;
15-
privateMaybeMethodInfosetter;
15+
[NonSerialized]
16+
privateMethodInfo?getter;
17+
[NonSerialized]
18+
privateMethodInfo?setter;
1619

1720
publicPropertyObject(PropertyInfomd)
1821
{
19-
getter=md.GetGetMethod(true);
20-
setter=md.GetSetMethod(true);
2122
info=newMaybeMemberInfo<PropertyInfo>(md);
23+
CacheAccessors();
24+
}
25+
26+
voidCacheAccessors()
27+
{
28+
PropertyInfomd=info.Value;
29+
getter=md.GetGetMethod(true)??md.GetBaseGetMethod(true);
30+
setter=md.GetSetMethod(true)??md.GetBaseSetMethod(true);
2231
}
2332

2433

@@ -35,7 +44,7 @@ public static NewReference tp_descr_get(BorrowedReference ds, BorrowedReference
3544
returnExceptions.RaiseTypeError(self.info.DeletedMessage);
3645
}
3746
varinfo=self.info.Value;
38-
MethodInfogetter=self.getter.UnsafeValue;
47+
MethodInfo?getter=self.getter;
3948
objectresult;
4049

4150

@@ -70,7 +79,7 @@ public static NewReference tp_descr_get(BorrowedReference ds, BorrowedReference
7079

7180
try
7281
{
73-
result=info.GetValue(co.inst,null);
82+
result=getter.Invoke(co.inst,Array.Empty<object>());
7483
returnConverter.ToPython(result,info.PropertyType);
7584
}
7685
catch(Exceptione)
@@ -100,7 +109,7 @@ public static int tp_descr_set(BorrowedReference ds, BorrowedReference ob, Borro
100109
}
101110
varinfo=self.info.Value;
102111

103-
MethodInfosetter=self.setter.UnsafeValue;
112+
MethodInfo?setter=self.setter;
104113

105114
if(val==null)
106115
{
@@ -141,7 +150,7 @@ public static int tp_descr_set(BorrowedReference ds, BorrowedReference ob, Borro
141150
Exceptions.RaiseTypeError("invalid target");
142151
return-1;
143152
}
144-
info.SetValue(co.inst,newval,null);
153+
setter.Invoke(co.inst,newobject?[]{newval});
145154
}
146155
else
147156
{
@@ -169,5 +178,13 @@ public static NewReference tp_repr(BorrowedReference ob)
169178
varself=(PropertyObject)GetManagedObject(ob)!;
170179
returnRuntime.PyString_FromString($"<property '{self.info}'>");
171180
}
181+
182+
voidIDeserializationCallback.OnDeserialization(objectsender)
183+
{
184+
if(info.Valid)
185+
{
186+
CacheAccessors();
187+
}
188+
}
172189
}
173190
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp