11using System ;
2+ using System . Diagnostics ;
23using System . Linq ;
34using System . Reflection ;
5+ using System . Runtime . Serialization ;
46
57namespace Python . Runtime
68{
@@ -13,18 +15,12 @@ namespace Python.Runtime
1315 [ Serializable ]
1416 internal class ClassObject : ClassBase
1517 {
16- internal ConstructorBinder binder ;
17- internal int NumCtors = 0 ;
18+ internal readonly int NumCtors = 0 ;
1819
1920 internal ClassObject ( Type tp ) : base ( tp )
2021 {
2122 var _ctors = type . Value . GetConstructors ( ) ;
2223 NumCtors = _ctors . Length ;
23- binder = new ConstructorBinder ( type . Value ) ;
24- foreach ( ConstructorInfo t in _ctors )
25- {
26- binder . AddMethod ( t ) ;
27- }
2824 }
2925
3026
@@ -33,7 +29,12 @@ internal ClassObject(Type tp) : base(tp)
3329 /// </summary>
3430 internal NewReference GetDocString ( )
3531 {
36- MethodBase [ ] methods = binder . GetMethods ( ) ;
32+ if ( ! type . Valid )
33+ {
34+ return Exceptions . RaiseTypeError ( type . DeletedMessage ) ;
35+ }
36+
37+ MethodBase [ ] methods = type . Value . GetConstructors ( ) ;
3738 var str = "" ;
3839 foreach ( MethodBase t in methods )
3940 {
@@ -50,7 +51,7 @@ internal NewReference GetDocString()
5051 /// <summary>
5152 /// Implements __new__ for reflected classes and value types.
5253 /// </summary>
53- public static NewReference tp_new ( BorrowedReference tp , BorrowedReference args , BorrowedReference kw )
54+ static NewReference tp_new_impl ( BorrowedReference tp , BorrowedReference args , BorrowedReference kw )
5455 {
5556 var self = GetManagedObject ( tp ) as ClassObject ;
5657
@@ -100,15 +101,49 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args,
100101 return NewEnum ( type , args , tp ) ;
101102 }
102103
103- object ? obj = self . binder . InvokeRaw ( null , args , kw ) ;
104- if ( obj == null )
104+ if ( IsGenericNullable ( type ) )
105105 {
106- return default ;
106+ // Nullable<T> has special handling in .NET runtime.
107+ // Invoking its constructor via reflection on an uninitialized instance
108+ // does not actually set the object fields.
109+ return NewNullable ( type , args , kw , tp ) ;
107110 }
108111
109- return CLRObject . GetReference ( obj , tp ) ;
112+ object obj = FormatterServices . GetUninitializedObject ( type ) ;
113+
114+ return self . NewObjectToPython ( obj , tp ) ;
115+ }
116+
117+ protected virtual void SetTypeNewSlot ( BorrowedReference pyType , SlotsHolder slotsHolder )
118+ {
119+ TypeManager . InitializeSlotIfEmpty ( pyType , TypeOffset . tp_new , new Interop . BBB_N ( tp_new_impl ) , slotsHolder ) ;
120+ }
121+
122+ public override bool HasCustomNew ( )
123+ {
124+ if ( base . HasCustomNew ( ) ) return true ;
125+
126+ Type clrType = type . Value ;
127+ return clrType . IsPrimitive
128+ || clrType . IsEnum
129+ || clrType == typeof ( string )
130+ || IsGenericNullable ( clrType ) ;
110131 }
111132
133+ static bool IsGenericNullable ( Type type )
134+ => type . IsValueType && type . IsGenericType
135+ && type . GetGenericTypeDefinition ( ) == typeof ( Nullable < > ) ;
136+
137+ public override void InitializeSlots ( BorrowedReference pyType , SlotsHolder slotsHolder )
138+ {
139+ base . InitializeSlots ( pyType , slotsHolder ) ;
140+
141+ this . SetTypeNewSlot ( pyType , slotsHolder ) ;
142+ }
143+
144+ protected virtual NewReference NewObjectToPython ( object obj , BorrowedReference tp )
145+ => CLRObject . GetReference ( obj , tp ) ;
146+
112147 private static NewReference NewEnum ( Type type , BorrowedReference args , BorrowedReference tp )
113148 {
114149 nint argCount = Runtime . PyTuple_Size ( args ) ;
@@ -146,6 +181,28 @@ private static NewReference NewEnum(Type type, BorrowedReference args, BorrowedR
146181 return CLRObject . GetReference ( enumValue , tp ) ;
147182 }
148183
184+ private static NewReference NewNullable ( Type type , BorrowedReference args , BorrowedReference kw , BorrowedReference tp )
185+ {
186+ Debug . Assert ( IsGenericNullable ( type ) ) ;
187+
188+ if ( kw != null )
189+ {
190+ return Exceptions . RaiseTypeError ( "System.Nullable<T> constructor does not support keyword arguments" ) ;
191+ }
192+
193+ nint argsCount = Runtime . PyTuple_Size ( args ) ;
194+ if ( argsCount != 1 )
195+ {
196+ return Exceptions . RaiseTypeError ( "System.Nullable<T> constructor expects 1 argument, got " + ( int ) argsCount ) ;
197+ }
198+
199+ var value = Runtime . PyTuple_GetItem ( args , 0 ) ;
200+ var elementType = type . GetGenericArguments ( ) [ 0 ] ;
201+ return Converter . ToManaged ( value , elementType , out var result , setError : true )
202+ ? CLRObject . GetReference ( result ! , tp )
203+ : default ;
204+ }
205+
149206
150207 /// <summary>
151208 /// Implementation of [] semantics for reflected types. This exists
0 commit comments