44using System . Reflection ;
55using System . Runtime . InteropServices ;
66using System . Security ;
7+ using System . Linq ;
78
89namespace Python . Runtime
910{
@@ -26,7 +27,6 @@ private ClassManager()
2627
2728 static ClassManager ( )
2829 {
29- cache = new Dictionary < Type , ClassBase > ( 128 ) ;
3030 // SEE: https://msdn.microsoft.com/en-us/library/96b1ayy4(v=vs.100).aspx
3131 // ""All delegates inherit from MulticastDelegate, which inherits from Delegate.""
3232 // Was Delegate, which caused a null MethodInfo returned from GetMethode("Invoke")
@@ -39,6 +39,49 @@ public static void Reset()
3939 cache = new Dictionary < Type , ClassBase > ( 128 ) ;
4040 }
4141
42+ public static IList < ClassBase > GetManagedTypes ( )
43+ {
44+ return cache . Values . ToArray ( ) ; // Make a copy.
45+ }
46+
47+ internal static void RemoveClasses ( )
48+ {
49+ var visited = new HashSet < IntPtr > ( ) ;
50+ var visitedHandle = GCHandle . Alloc ( visited ) ;
51+ var visitedPtr = ( IntPtr ) visitedHandle ;
52+ try
53+ {
54+ foreach ( var cls in cache . Values )
55+ {
56+ cls . TypeTraverse ( OnVisit , visitedPtr ) ;
57+ // XXX: Force release some resouces.
58+ cls . TypeClear ( ) ;
59+ //Runtime.XDecref(cls.pyHandle);
60+ }
61+ }
62+ finally
63+ {
64+ visitedHandle . Free ( ) ;
65+ }
66+ }
67+
68+ private static int OnVisit ( IntPtr ob , IntPtr arg )
69+ {
70+ var visited = ( HashSet < IntPtr > ) GCHandle . FromIntPtr ( arg ) . Target ;
71+ if ( visited . Contains ( ob ) )
72+ {
73+ return 0 ;
74+ }
75+ visited . Add ( ob ) ;
76+ var clrObj = ManagedType . GetManagedObject ( ob ) ;
77+ if ( clrObj != null )
78+ {
79+ clrObj . TypeTraverse ( OnVisit , arg ) ;
80+ clrObj . TypeClear ( ) ;
81+ }
82+ return 0 ;
83+ }
84+
4285 /// <summary>
4386 /// Return the ClassBase-derived instance that implements a particular
4487 /// reflected managed type, creating it if it doesn't yet exist.
@@ -134,7 +177,6 @@ private static void InitClassBase(Type type, ClassBase impl)
134177
135178
136179 IntPtr tp = TypeManager . GetTypeHandle ( impl , type ) ;
137- impl . tpHandle = tp ;
138180
139181 // Finally, initialize the class __dict__ and return the object.
140182 IntPtr dict = Marshal . ReadIntPtr ( tp , TypeOffset . tp_dict ) ;
@@ -146,6 +188,9 @@ private static void InitClassBase(Type type, ClassBase impl)
146188 var item = ( ManagedType ) iter . Value ;
147189 var name = ( string ) iter . Key ;
148190 Runtime . PyDict_SetItemString ( dict , name , item . pyHandle ) ;
191+ // info.members are already useless
192+ Runtime . XDecref ( item . pyHandle ) ;
193+ item . pyHandle = IntPtr . Zero ;
149194 }
150195
151196 // If class has constructors, generate an __doc__ attribute.
0 commit comments