@@ -66,10 +66,7 @@ private static CallSite<Func<CallSite, object, object, object>> SetAttrCallSite(
6666 /// </summary>
6767 public static NewReference tp_getattro ( BorrowedReference ob , BorrowedReference key )
6868 {
69- var result = Runtime . PyObject_GenericGetAttr ( ob , key ) ;
70-
71- // If AttributeError was raised, we try to get the attribute from the managed object dynamic properties.
72- if ( Exceptions . ExceptionMatches ( Exceptions . AttributeError ) )
69+ if ( ! TryGetNonDynamicMember ( ob , key , out var result ) )
7370 {
7471 var clrObj = ( CLRObject ) GetManagedObject ( ob ) ! ;
7572
@@ -103,20 +100,14 @@ public static NewReference tp_getattro(BorrowedReference ob, BorrowedReference k
103100 /// </summary>
104101 public static int tp_setattro ( BorrowedReference ob , BorrowedReference key , BorrowedReference val )
105102 {
106- var clrObj = ( CLRObject ) GetManagedObject ( ob ) ! ;
107- var name = Runtime . GetManagedString ( key ) ;
108-
109- // If the key corresponds to a valid property or field of the class, we let the default implementation handle it.
110- var clrObjectType = clrObj . inst . GetType ( ) ;
111- var bindingFlags = BindingFlags . Instance | BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ;
112- var property = clrObjectType . GetProperty ( name , bindingFlags ) ;
113- var field = property == null ? clrObjectType . GetField ( name , bindingFlags ) : null ;
114- if ( ( property != null && property . SetMethod != null ) || field != null )
103+ if ( TryGetNonDynamicMember ( ob , key , out _ , clearExceptions : true ) )
115104 {
116105 return Runtime . PyObject_GenericSetAttr ( ob , key , val ) ;
117106 }
118107
119- var callsite = SetAttrCallSite ( name , clrObjectType ) ;
108+ var clrObj = ( CLRObject ) GetManagedObject ( ob ) ! ;
109+ var name = Runtime . GetManagedString ( key ) ;
110+ var callsite = SetAttrCallSite ( name , clrObj . inst . GetType ( ) ) ;
120111 try
121112 {
122113 callsite . Target ( callsite , clrObj . inst , PyObject . FromNullableReference ( val ) ) ;
@@ -129,5 +120,19 @@ public static int tp_setattro(BorrowedReference ob, BorrowedReference key, Borro
129120
130121 return 0 ;
131122 }
123+
124+ private static bool TryGetNonDynamicMember ( BorrowedReference ob , BorrowedReference key , out NewReference value , bool clearExceptions = false )
125+ {
126+ value = Runtime . PyObject_GenericGetAttr ( ob , key ) ;
127+ // If AttributeError was raised, we try to get the attribute from the managed object dynamic properties.
128+ var result = ! Exceptions . ExceptionMatches ( Exceptions . AttributeError ) ;
129+
130+ if ( clearExceptions )
131+ {
132+ Exceptions . Clear ( ) ;
133+ }
134+
135+ return result ;
136+ }
132137 }
133138}
0 commit comments