@@ -28,18 +28,39 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
2828 return false ;
2929 }
3030
31- using ( var pyList = PyList . AsList ( pyObj ) )
31+ if ( typeof ( T ) . IsGenericType )
3232 {
33- if ( typeof ( T ) . IsGenericType )
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 < > ) ) )
3437 {
35- value = pyList . ToList < T > ( ) ;
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 ;
3652 }
37- else
53+
54+ using ( var pyList = PyList . AsList ( pyObj ) )
3855 {
39- value = ( T ) pyList . ToList ( ) ;
56+ value = pyList . ToList < T > ( ) ;
4057 }
4158 return true ;
4259 }
60+
61+ var converted = ConvertToArrayList ( pyObj ) ;
62+ value = ( T ) converted ;
63+ return true ;
4364 }
4465
4566 public PyObject TryEncode ( object value )
@@ -57,5 +78,105 @@ bool IPyObjectDecoder.CanDecode(PyType objectType, Type targetType)
5778 }
5879 return decodableTypes . IndexOf ( targetType ) >= 0 ;
5980 }
81+
82+ private static IList ConvertToArrayList ( PyObject pyObj )
83+ {
84+ using var pyList = PyList . AsList ( pyObj ) ;
85+ var result = new ArrayList ( ) ;
86+ foreach ( PyObject item in pyList )
87+ {
88+ using ( item )
89+ {
90+ result . Add ( ConvertItem ( item ) ) ;
91+ }
92+ }
93+ return result ;
94+ }
95+
96+ private static object ConvertItem ( PyObject item )
97+ {
98+ if ( TryGetClrObject ( item , out var clrObject ) )
99+ {
100+ return clrObject ;
101+ }
102+
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+
119+ if ( PyString . IsStringType ( item ) )
120+ {
121+ return item . AsManagedObject ( typeof ( string ) ) ;
122+ }
123+
124+ if ( PyList . IsListType ( item ) || PyTuple . IsTupleType ( item ) )
125+ {
126+ return ConvertToArrayList ( item ) ;
127+ }
128+
129+ return item . AsManagedObject ( typeof ( object ) ) ;
130+ }
131+
132+ private static bool TryGetClrObject ( PyObject pyObj , out object clrObject )
133+ {
134+ try
135+ {
136+ clrObject = pyObj . GetManagedObject ( ) ;
137+ if ( clrObject is PyObject || clrObject is null )
138+ {
139+ clrObject = null ;
140+ return false ;
141+ }
142+ return true ;
143+ }
144+ catch
145+ {
146+ clrObject = null ;
147+ return false ;
148+ }
149+ }
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+ }
60181 }
61182}
0 commit comments