11using System ;
2+ using System . Linq ;
23
34namespace Python . Runtime
45{
@@ -20,10 +21,58 @@ internal GenericType(Type tp) : base(tp)
2021 /// </summary>
2122 public static NewReference tp_new ( BorrowedReference tp , BorrowedReference args , BorrowedReference kw )
2223 {
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+
2341 Exceptions . SetError ( Exceptions . TypeError , "cannot instantiate an open generic type" ) ;
42+
2443 return default ;
2544 }
2645
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+ }
2776
2877 /// <summary>
2978 /// Implements __call__ for reflected generic types.
0 commit comments