| File: System\ActivatorImplementation.cs | Web Access |
| Project: src\runtime\src\coreclr\nativeaot\System.Private.CoreLib\src\System.Private.CoreLib.csproj (System.Private.CoreLib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using System.Reflection.Runtime.BindingFlagSupport; using System.Reflection.Runtime.General; using Internal.Runtime.Augments; namespace System { internal static class ActivatorImplementation { [DebuggerGuidedStepThrough] public static object CreateInstance( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type, bool nonPublic) { ArgumentNullException.ThrowIfNull(type); type = type.UnderlyingSystemType; CreateInstanceCheckType(type); BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; if (nonPublic) bindingFlags |= BindingFlags.NonPublic; ConstructorInfo? constructor = type.GetConstructor(bindingFlags, null, CallingConventions.Any, Array.Empty<Type>(), null); if (constructor == null) { if (type.IsValueType) { RuntimeTypeHandle typeHandle = type.TypeHandle; if (RuntimeAugments.IsNullable(typeHandle)) return null; return RuntimeAugments.RawNewObject(typeHandle); } throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, type)); } object result = constructor.Invoke(Array.Empty<object>()); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } [DebuggerGuidedStepThrough] public static object CreateInstance( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type, BindingFlags bindingAttr, Binder binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { ArgumentNullException.ThrowIfNull(type); // If they didn't specify a lookup, then we will provide the default lookup. const BindingFlags LookupMask = (BindingFlags)0x000000FF; if ((bindingAttr & LookupMask) == 0) bindingAttr |= BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance; if (activationAttributes != null && activationAttributes.Length > 0) throw new PlatformNotSupportedException(SR.NotSupported_ActivAttr); type = type.UnderlyingSystemType; CreateInstanceCheckType(type); args ??= Array.Empty<object>(); int numArgs = args.Length; Type?[] argTypes = new Type[numArgs]; for (int i = 0; i < numArgs; i++) { argTypes[i] = args[i]?.GetType(); } ConstructorInfo[] candidates = type.GetConstructors(bindingAttr); ListBuilder<MethodBase> matches = new ListBuilder<MethodBase>(candidates.Length); for (int i = 0; i < candidates.Length; i++) { if (candidates[i].QualifiesBasedOnParameterCount(bindingAttr, CallingConventions.Any, argTypes)) matches.Add(candidates[i]); } if (matches.Count == 0) { if (numArgs == 0 && type.IsValueType) { RuntimeTypeHandle typeHandle = type.TypeHandle; if (RuntimeAugments.IsNullable(typeHandle)) return null; return RuntimeAugments.RawNewObject(typeHandle); } throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, type)); } binder ??= Type.DefaultBinder; MethodBase? invokeMethod; object? state; try { invokeMethod = binder.BindToMethod(bindingAttr, matches.ToArray(), ref args, null, culture, null, out state); } catch (MissingMethodException innerMME) { // Rethrows to rewrite a message to include the class name. // Make sure the original exception is set as an inner exception. throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, type), innerMME); } if (invokeMethod == null) { throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, type)); } if (invokeMethod.GetParametersAsSpan().Length == 0) { if (args.Length != 0) { Debug.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs); throw new NotSupportedException(SR.NotSupported_CallToVarArg); } // Desktop compat: CoreClr invokes a "fast-path" here (call Activator.CreateInstance(type, true)) that also // bypasses the binder.ReorderArgumentArray() call. That "fast-path" isn't a fast-path for us so we won't do that // but we'll still null out the "state" variable to bypass the Reorder call. // // The only time this matters at all is if (1) a third party binder is being used and (2) it actually reordered the array // which it shouldn't have done because (a) we didn't request it to bind arguments by name, and (b) it's kinda hard to // reorder a zero-length args array. But who knows what a third party binder will do if we make a call to it that we didn't // used to do, so we'll preserve the CoreClr order of calls just to be safe. state = null; } object result = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); if (state != null) binder.ReorderArgumentArray(ref args, state); return result; } private static void CreateInstanceCheckType(Type type) { if (type is not RuntimeType) throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); if (type.IsAbstract) throw new MissingMethodException(type.IsInterface ? SR.Acc_CreateInterface : SR.Acc_CreateAbst); // Strange but compatible exception. if (type.ContainsGenericParameters) throw new ArgumentException(SR.Format(SR.Acc_CreateGenericEx, type)); if (type.IsByRefLike) throw new NotSupportedException(SR.NotSupported_ByRefLike); Type elementType = type; while (elementType.HasElementType) elementType = elementType.GetElementType()!; if (elementType == typeof(void)) throw new NotSupportedException(SR.Acc_CreateVoid); } } }