1
1
using System ;
2
+ using System . Linq ;
2
3
3
4
namespace Python . Runtime
4
5
{
@@ -20,10 +21,58 @@ internal GenericType(Type tp) : base(tp)
20
21
/// </summary>
21
22
public static NewReference tp_new ( BorrowedReference tp , BorrowedReference args , BorrowedReference kw )
22
23
{
24
+ var self = ( GenericType ) GetManagedObject ( tp ) ! ;
25
+ if ( ! self . type . Valid )
26
+ {
27
+ return Exceptions . RaiseTypeError ( self . type . DeletedMessage ) ;
28
+ }
29
+ var type = self . type . Value ;
30
+
31
+ if ( type . IsInterface && ! type . IsConstructedGenericType )
32
+ {
33
+ var nargs = Runtime . PyTuple_Size ( args ) ;
34
+ if ( nargs == 1 )
35
+ {
36
+ var instance = Runtime . PyTuple_GetItem ( args , 0 ) ;
37
+ return AsGenericInterface ( instance , type ) ;
38
+ }
39
+ }
40
+
23
41
Exceptions . SetError ( Exceptions . TypeError , "cannot instantiate an open generic type" ) ;
42
+
24
43
return default ;
25
44
}
26
45
46
+ static NewReference AsGenericInterface ( BorrowedReference instance , Type targetType )
47
+ {
48
+ if ( GetManagedObject ( instance ) is not CLRObject obj )
49
+ {
50
+ return Exceptions . RaiseTypeError ( "only .NET objects can be cast to .NET interfaces" ) ;
51
+ }
52
+
53
+ Type [ ] supportedInterfaces = obj . inst . GetType ( ) . GetInterfaces ( ) ;
54
+ Type [ ] constructedInterfaces = supportedInterfaces
55
+ . Where ( i => i . IsConstructedGenericType && i . GetGenericTypeDefinition ( ) == targetType )
56
+ . ToArray ( ) ;
57
+
58
+ if ( constructedInterfaces . Length == 1 )
59
+ {
60
+ BorrowedReference pythonic = ClassManager . GetClass ( constructedInterfaces [ 0 ] ) ;
61
+ using var args = Runtime . PyTuple_New ( 1 ) ;
62
+ Runtime . PyTuple_SetItem ( args . Borrow ( ) , 0 , instance ) ;
63
+ return Runtime . PyObject_CallObject ( pythonic , args . Borrow ( ) ) ;
64
+ }
65
+
66
+ if ( constructedInterfaces . Length > 1 )
67
+ {
68
+ string interfaces = string . Join ( ", " , constructedInterfaces . Select ( TypeManager . GetPythonTypeName ) ) ;
69
+ return Exceptions . RaiseTypeError ( "Ambiguous cast to .NET interface. "
70
+ + $ "Object implements: { interfaces } ") ;
71
+ }
72
+
73
+ return Exceptions . RaiseTypeError ( "object does not implement "
74
+ + TypeManager . GetPythonTypeName ( targetType ) ) ;
75
+ }
27
76
28
77
/// <summary>
29
78
/// Implements __call__ for reflected generic types.
0 commit comments