@@ -30,6 +30,27 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
3030
3131 if ( typeof ( T ) . IsGenericType )
3232 {
33+ var genericDef = typeof ( T ) . GetGenericTypeDefinition ( ) ;
34+ var elementType = typeof ( T ) . GetGenericArguments ( ) . FirstOrDefault ( ) ;
35+
36+ if ( elementType != null && ( genericDef == typeof ( IEnumerable < > ) || genericDef == typeof ( List < > ) || genericDef == typeof ( IList < > ) ) )
37+ {
38+ using var pyList = PyList . AsList ( pyObj ) ;
39+ var listType = typeof ( List < > ) . MakeGenericType ( elementType ) ;
40+ var typedList = ( IList ) Activator . CreateInstance ( listType ) ! ;
41+
42+ foreach ( PyObject item in pyList )
43+ {
44+ using ( item )
45+ {
46+ typedList . Add ( ConvertGenericItem ( item , elementType ) ) ;
47+ }
48+ }
49+
50+ value = ( T ) typedList ;
51+ return true ;
52+ }
53+
3354 using ( var pyList = PyList . AsList ( pyObj ) )
3455 {
3556 value = pyList . ToList < T > ( ) ;
@@ -79,6 +100,22 @@ private static object ConvertItem(PyObject item)
79100 return clrObject ;
80101 }
81102
103+ if ( PyInt . IsIntType ( item ) )
104+ {
105+ using var pyLong = PyInt . AsInt ( item ) ;
106+ try { return pyLong . ToInt64 ( ) ; }
107+ catch ( PythonException ex ) when ( ex . Message . StartsWith ( "int too big" ) )
108+ {
109+ return pyLong . ToBigInteger ( ) ;
110+ }
111+ }
112+
113+ if ( PyFloat . IsFloatType ( item ) )
114+ {
115+ using var pyFloat = PyFloat . AsFloat ( item ) ;
116+ return pyFloat . ToDouble ( ) ;
117+ }
118+
82119 if ( PyString . IsStringType ( item ) )
83120 {
84121 return item . AsManagedObject ( typeof ( string ) ) ;
@@ -97,13 +134,49 @@ private static bool TryGetClrObject(PyObject pyObj, out object clrObject)
97134 try
98135 {
99136 clrObject = pyObj . GetManagedObject ( ) ;
100- return clrObject != null ;
137+ if ( clrObject is PyObject || clrObject is null )
138+ {
139+ clrObject = null ;
140+ return false ;
141+ }
142+ return true ;
101143 }
102144 catch
103145 {
104146 clrObject = null ;
105147 return false ;
106148 }
107149 }
150+
151+ private static object ConvertGenericItem ( PyObject item , Type elementType )
152+ {
153+ if ( elementType == typeof ( object ) )
154+ {
155+ return ConvertItem ( item ) ;
156+ }
157+
158+ if ( TryGetClrObject ( item , out var clrObject ) && elementType . IsInstanceOfType ( clrObject ) )
159+ {
160+ return clrObject ;
161+ }
162+
163+ if ( PyList . IsListType ( item ) || PyTuple . IsTupleType ( item ) )
164+ {
165+ // recursively decode nested generics
166+ var listType = typeof ( List < > ) . MakeGenericType ( elementType ) ;
167+ var nestedList = ( IList ) Activator . CreateInstance ( listType ) ! ;
168+ using var pyList = PyList . AsList ( item ) ;
169+ foreach ( PyObject child in pyList )
170+ {
171+ using ( child )
172+ {
173+ nestedList . Add ( ConvertGenericItem ( child , elementType ) ) ;
174+ }
175+ }
176+ return nestedList ;
177+ }
178+
179+ return item . AsManagedObject ( elementType ) ;
180+ }
108181 }
109182}
0 commit comments