11using System ;
22using System . Collections ;
3+ using System . Collections . Generic ;
34using System . Globalization ;
45using System . Runtime . InteropServices ;
56using System . Security ;
@@ -166,19 +167,20 @@ internal static IntPtr ToPython(object value, Type type)
166167 return result ;
167168 }
168169
169- if ( value is IList && value . GetType ( ) . IsGenericType )
170+ var list = value as IList ;
171+ if ( list != null && value . GetType ( ) . IsGenericType )
170172 {
171- using ( var resultlist = new PyList ( ) )
173+ using ( var resultList = new PyList ( ) )
172174 {
173- foreach ( object o in ( IEnumerable ) value )
175+ for ( var i = 0 ; i < list . Count ; i ++ )
174176 {
175- using ( var p = new PyObject ( ToPython ( o , o ? . GetType ( ) ) ) )
177+ using ( var p = list [ i ] . ToPython ( ) )
176178 {
177- resultlist . Append ( p ) ;
179+ resultList . Append ( p ) ;
178180 }
179181 }
180- Runtime . XIncref ( resultlist . Handle ) ;
181- return resultlist . Handle ;
182+ Runtime . XIncref ( resultList . Handle ) ;
183+ return resultList . Handle ;
182184 }
183185 }
184186
@@ -382,6 +384,15 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
382384 return true ;
383385 }
384386
387+ if ( obType . IsGenericType && Runtime . PyObject_TYPE ( value ) == Runtime . PyListType )
388+ {
389+ var typeDefinition = obType . GetGenericTypeDefinition ( ) ;
390+ if ( typeDefinition == typeof ( List < > ) )
391+ {
392+ return ToList ( value , obType , out result , setError ) ;
393+ }
394+ }
395+
385396 // Common case: if the Python value is a wrapped managed object
386397 // instance, just return the wrapped object.
387398 ManagedType mt = ManagedType . GetManagedObject ( value ) ;
@@ -1003,7 +1014,6 @@ private static void SetConversionError(IntPtr value, Type target)
10031014 Exceptions . SetError ( Exceptions . TypeError , $ "Cannot convert { src } to { target } ") ;
10041015 }
10051016
1006-
10071017 /// <summary>
10081018 /// Convert a Python value to a correctly typed managed array instance.
10091019 /// The Python value must support the Python sequence protocol and the
@@ -1015,7 +1025,7 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
10151025 int size = Runtime . PySequence_Size ( value ) ;
10161026 result = null ;
10171027
1018- if ( size < 0 || elementType . IsGenericType )
1028+ if ( elementType . IsGenericType )
10191029 {
10201030 if ( setError )
10211031 {
@@ -1026,7 +1036,49 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
10261036
10271037 Array items = Array . CreateInstance ( elementType , size ) ;
10281038
1029- // XXX - is there a better way to unwrap this if it is a real array?
1039+ var index = 0 ;
1040+ result = items ;
1041+ return ApplyActionToPySequence ( value , obType , setError , size , elementType , o =>
1042+ {
1043+ items . SetValue ( o , index ++ ) ;
1044+ } ) ;
1045+ }
1046+
1047+ /// <summary>
1048+ /// Convert a Python value to a correctly typed managed list instance.
1049+ /// The Python value must support the Python sequence protocol and the
1050+ /// items in the sequence must be convertible to the target list type.
1051+ /// </summary>
1052+ private static bool ToList ( IntPtr value , Type obType , out object result , bool setError )
1053+ {
1054+ var elementType = obType . GetGenericArguments ( ) [ 0 ] ;
1055+ var size = Runtime . PySequence_Size ( value ) ;
1056+
1057+ result = Activator . CreateInstance ( obType , args : size ) ;
1058+ var resultList = ( IList ) result ;
1059+ return ApplyActionToPySequence ( value , obType , setError , size , elementType , o => resultList . Add ( o ) ) ;
1060+ }
1061+
1062+ /// <summary>
1063+ /// Helper method that will enumerate a Python sequence convert its values to the given
1064+ /// type and send them to the provided action
1065+ /// </summary>
1066+ private static bool ApplyActionToPySequence ( IntPtr value ,
1067+ Type obType ,
1068+ bool setError ,
1069+ int size ,
1070+ Type elementType ,
1071+ Action < object > action )
1072+ {
1073+ if ( size < 0 )
1074+ {
1075+ if ( setError )
1076+ {
1077+ SetConversionError ( value , obType ) ;
1078+ }
1079+ return false ;
1080+ }
1081+
10301082 for ( var i = 0 ; i < size ; i ++ )
10311083 {
10321084 object obj = null ;
@@ -1046,15 +1098,13 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
10461098 return false ;
10471099 }
10481100
1049- items . SetValue ( obj , i ) ;
1101+ action ( obj ) ;
10501102 Runtime . XDecref ( item ) ;
10511103 }
10521104
1053- result = items ;
10541105 return true ;
10551106 }
10561107
1057-
10581108 /// <summary>
10591109 /// Convert a Python value to a correctly typed managed enum instance.
10601110 /// </summary>
0 commit comments