1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 //
6 // Activator is an object that contains the Activation (CreateInstance/New)
7 //  methods for late bound support.
8 //
9 
10 using System.Diagnostics;
11 using System.Globalization;
12 using System.Reflection;
13 using System.Runtime.CompilerServices;
14 using System.Runtime;
15 
16 using Internal.Reflection.Augments;
17 
18 namespace System
19 {
20     public static class Activator
21     {
22         // The following 2 methods and helper class implement the functionality of Activator.CreateInstance<T>()
23 
24         // This method is the public surface area. It wraps the CreateInstance intrinsic with the appropriate try/catch
25         // block so that the correct exceptions are generated. Also, it handles the cases where the T type doesn't have
26         // a default constructor. (Those result in running the ClassWithMissingConstructor's .ctor, which flips the magic
27         // thread static to cause the CreateInstance<T> method to throw the right exception.)
28         //
29         [DebuggerGuidedStepThrough]
CreateInstance()30         public static T CreateInstance<T>()
31         {
32             T t = default(T);
33 
34             bool missingDefaultConstructor = false;
35 
36             EETypePtr eetype = EETypePtr.EETypePtrOf<T>();
37 
38             if (!RuntimeHelpers.IsReference<T>())
39             {
40                 // Early out for valuetypes since we don't support default constructors anyway.
41                 // This lets codegens that expand IsReference<T> optimize away the rest of this code.
42             }
43             else if (eetype.ComponentSize != 0)
44             {
45                 // ComponentSize > 0 indicates an array-like type (e.g. string, array, etc).
46                 // Allocating this using the normal allocator would result in silent heap corruption.
47                 missingDefaultConstructor = true;
48             }
49             else if (eetype.IsInterface)
50             {
51                 // Do not attempt to allocate interface types either
52                 missingDefaultConstructor = true;
53             }
54             else
55             {
56                 bool oldValueOfMissingDefaultCtorMarkerBool = s_createInstanceMissingDefaultConstructor;
57 
58                 try
59                 {
60 #if PROJECTN
61                     t = CreateInstanceIntrinsic<T>();
62                     DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
63 #else
64                     t = (T)(RuntimeImports.RhNewObject(eetype));
65 
66                     // Run the default constructor. If the default constructor was missing, codegen
67                     // will expand DefaultConstructorOf to ClassWithMissingConstructor::.ctor
68                     // and we detect that later.
69                     IntPtr defaultConstructor = DefaultConstructorOf<T>();
70                     RawCalliHelper.Call(defaultConstructor, t);
71                     DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
72 #endif
73                 }
74                 catch (Exception e)
75                 {
76                     throw new TargetInvocationException(e);
77                 }
78 
79                 if (s_createInstanceMissingDefaultConstructor != oldValueOfMissingDefaultCtorMarkerBool)
80                 {
81                     missingDefaultConstructor = true;
82 
83                     // We didn't call the real .ctor (because there wasn't one), but we still allocated
84                     // an uninitialized object. If it has a finalizer, it would run - prevent that.
85                     GC.SuppressFinalize(t);
86                 }
87             }
88 
89             if (missingDefaultConstructor)
90             {
91                 throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, typeof(T)));
92             }
93 
94             return t;
95         }
96 
97         [Intrinsic]
CreateInstanceIntrinsic()98         private extern static T CreateInstanceIntrinsic<T>();
99 
100         [Intrinsic]
DefaultConstructorOf()101         private static IntPtr DefaultConstructorOf<T>()
102         {
103             // Codegens must expand this intrinsic.
104             // We could implement a fallback with the type loader if we wanted to, but it will be slow and unreliable.
105             throw new NotSupportedException();
106         }
107 
108         [ThreadStatic]
109         internal static bool s_createInstanceMissingDefaultConstructor;
110         internal class ClassWithMissingConstructor
111         {
ClassWithMissingConstructor()112             private ClassWithMissingConstructor()
113             {
114                 s_createInstanceMissingDefaultConstructor = !s_createInstanceMissingDefaultConstructor;
115             }
MissingDefaultConstructorStaticEntryPoint()116             internal static void MissingDefaultConstructorStaticEntryPoint()
117             {
118                 s_createInstanceMissingDefaultConstructor = !s_createInstanceMissingDefaultConstructor;
119             }
120         }
121 
122         [DebuggerHidden]
123         [DebuggerStepThrough]
124         public static object CreateInstance(Type type) => CreateInstance(type, nonPublic: false);
125 
126         [DebuggerHidden]
127         [DebuggerStepThrough]
CreateInstance(Type type, bool nonPublic)128         public static object CreateInstance(Type type, bool nonPublic) => ReflectionAugments.ReflectionCoreCallbacks.ActivatorCreateInstance(type, nonPublic);
129 
130         [DebuggerHidden]
131         [DebuggerStepThrough]
CreateInstance(Type type, params object[] args)132         public static object CreateInstance(Type type, params object[] args) => CreateInstance(type, ConstructorDefault, null, args, null, null);
133 
134         [DebuggerHidden]
135         [DebuggerStepThrough]
CreateInstance(Type type, object[] args, object[] activationAttributes)136         public static object CreateInstance(Type type, object[] args, object[] activationAttributes) => CreateInstance(type, ConstructorDefault, null, args, null, activationAttributes);
137 
138         [DebuggerHidden]
139         [DebuggerStepThrough]
CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture)140         public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture) => CreateInstance(type, bindingAttr, binder, args, culture, null);
141 
142         [DebuggerHidden]
143         [DebuggerStepThrough]
CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes)144         public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes)
145         {
146             return ReflectionAugments.ReflectionCoreCallbacks.ActivatorCreateInstance(type, bindingAttr, binder, args, culture, activationAttributes);
147         }
148 
149         private const BindingFlags ConstructorDefault = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
150     }
151 }
152 
153