1
1
using System ;
2
+ using System . Diagnostics ;
2
3
using System . Linq ;
3
4
using System . Reflection ;
5
+ using System . Runtime . Serialization ;
4
6
5
7
namespace Python . Runtime
6
8
{
@@ -13,18 +15,12 @@ namespace Python.Runtime
13
15
[ Serializable ]
14
16
internal class ClassObject : ClassBase
15
17
{
16
- internal ConstructorBinder binder ;
17
- internal int NumCtors = 0 ;
18
+ internal readonly int NumCtors = 0 ;
18
19
19
20
internal ClassObject ( Type tp ) : base ( tp )
20
21
{
21
22
var _ctors = type . Value . GetConstructors ( ) ;
22
23
NumCtors = _ctors . Length ;
23
- binder = new ConstructorBinder ( type . Value ) ;
24
- foreach ( ConstructorInfo t in _ctors )
25
- {
26
- binder . AddMethod ( t ) ;
27
- }
28
24
}
29
25
30
26
@@ -33,7 +29,12 @@ internal ClassObject(Type tp) : base(tp)
33
29
/// </summary>
34
30
internal NewReference GetDocString ( )
35
31
{
36
- MethodBase [ ] methods = binder . GetMethods ( ) ;
32
+ if ( ! type . Valid )
33
+ {
34
+ return Exceptions . RaiseTypeError ( type . DeletedMessage ) ;
35
+ }
36
+
37
+ MethodBase [ ] methods = type . Value . GetConstructors ( ) ;
37
38
var str = "" ;
38
39
foreach ( MethodBase t in methods )
39
40
{
@@ -50,7 +51,7 @@ internal NewReference GetDocString()
50
51
/// <summary>
51
52
/// Implements __new__ for reflected classes and value types.
52
53
/// </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 )
54
55
{
55
56
var self = GetManagedObject ( tp ) as ClassObject ;
56
57
@@ -100,15 +101,49 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args,
100
101
return NewEnum ( type , args , tp ) ;
101
102
}
102
103
103
- object ? obj = self . binder . InvokeRaw ( null , args , kw ) ;
104
- if ( obj == null )
104
+ if ( IsGenericNullable ( type ) )
105
105
{
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 ) ;
107
110
}
108
111
109
- return CLRObject . GetReference ( obj , tp ) ;
112
+ object obj = FormatterServices . GetUninitializedObject ( type ) ;
113
+
114
+ return self . NewObjectToPython ( obj , tp ) ;
115
+ }
116
+
117
+ protected virtual bool DefinesTypeNew ( ) => true ;
118
+
119
+ public override bool ExposesClrConstructors ( )
120
+ {
121
+ if ( ! base . ExposesClrConstructors ( ) ) return false ;
122
+
123
+ Type clrType = type . Value ;
124
+ return ! clrType . IsPrimitive
125
+ && ! clrType . IsEnum
126
+ && clrType != typeof ( string )
127
+ && ! IsGenericNullable ( clrType ) ;
128
+ }
129
+
130
+ static bool IsGenericNullable ( Type type )
131
+ => type . IsValueType && type . IsGenericType
132
+ && type . GetGenericTypeDefinition ( ) == typeof ( Nullable < > ) ;
133
+
134
+ public override void InitializeSlots ( BorrowedReference pyType , SlotsHolder slotsHolder )
135
+ {
136
+ base . InitializeSlots ( pyType , slotsHolder ) ;
137
+
138
+ if ( DefinesTypeNew ( ) )
139
+ {
140
+ TypeManager . InitializeSlotIfEmpty ( pyType , TypeOffset . tp_new , new Interop . BBB_N ( tp_new_impl ) , slotsHolder ) ;
141
+ }
110
142
}
111
143
144
+ protected virtual NewReference NewObjectToPython ( object obj , BorrowedReference tp )
145
+ => CLRObject . GetReference ( obj , tp ) ;
146
+
112
147
private static NewReference NewEnum ( Type type , BorrowedReference args , BorrowedReference tp )
113
148
{
114
149
nint argCount = Runtime . PyTuple_Size ( args ) ;
@@ -146,6 +181,28 @@ private static NewReference NewEnum(Type type, BorrowedReference args, BorrowedR
146
181
return CLRObject . GetReference ( enumValue , tp ) ;
147
182
}
148
183
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
+
149
206
150
207
/// <summary>
151
208
/// Implementation of [] semantics for reflected types. This exists
0 commit comments