| File: System\Reflection\Assembly.NativeAot.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.Configuration.Assemblies; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Security; using Internal.Reflection.Augments; namespace System.Reflection { public abstract partial class Assembly : ICustomAttributeProvider, ISerializable { private static Assembly? GetEntryAssemblyInternal() => Internal.Runtime.CompilerHelpers.StartupCodeHelpers.GetEntryAssembly(); [System.Runtime.CompilerServices.Intrinsic] public static Assembly GetExecutingAssembly() { throw NotImplemented.ByDesign; } //Implemented by toolchain. [DynamicSecurityMethod] public static Assembly GetCallingAssembly() { if (AppContext.TryGetSwitch("Switch.System.Reflection.Assembly.SimulatedCallingAssembly", out bool isSimulated) && isSimulated) return GetEntryAssembly(); if (!StackTrace.IsSupported) throw new NotSupportedException(SR.NotSupported_StackTraceSupportDisabled); // We're interested in the frame that called the method that calls GetCallingAssembly // (skipFrames: 2), but we walk the stack so that we can skip any compiler-generated // thunks that don't have method info, as well as the static constructor invocation // machinery (matching what CoreCLR skips when looking for the caller). // The for loop typically only runs one iteration. DiagnosticMethodInfo? dmi = null; for (int i = 2; ; i++) { var frame = new StackFrame(i); // A zero IP address means we walked off the top of the stack without finding anything. if (frame.GetNativeIPAddress() == IntPtr.Zero) break; dmi = DiagnosticMethodInfo.Create(frame); if (dmi == null) continue; // Skip the static constructor invocation machinery so that a GetCallingAssembly // called from a class constructor sees the assembly that triggered the cctor. if (dmi.DeclaringTypeName == $"System.Runtime.CompilerServices.{nameof(ClassConstructorRunner)}" && dmi.DeclaringAssemblyName?.StartsWith(CoreLib.Name, StringComparison.Ordinal) == true) { dmi = null; continue; } break; } // If we haven't found anything, fall back to the method that called GetCallingAssembly. // This simulates what CoreCLR would do if GetCallingAssembly is called from e.g. Main. dmi ??= DiagnosticMethodInfo.Create(new StackFrame(1)); return dmi?.DeclaringAssemblyName is string asmName ? Load(asmName) : null; } public static Assembly Load(AssemblyName assemblyRef) => ReflectionAugments.Load(assemblyRef, throwOnFileNotFound: true); public static Assembly Load(string assemblyString) { ArgumentNullException.ThrowIfNull(assemblyString); AssemblyName name = new AssemblyName(assemblyString); return Load(name); } // Performance metric to count the number of assemblies internal static uint GetAssemblyCount() { return (uint)Internal.Reflection.Core.Execution.ReflectionCoreExecution.ExecutionEnvironment.AssemblyBinder.GetLoadedAssembliesCount(); } [Obsolete("Assembly.LoadWithPartialName has been deprecated. Use Assembly.Load() instead.")] public static Assembly LoadWithPartialName(string partialName) { ArgumentNullException.ThrowIfNull(partialName); if ((partialName.Length == 0) || (partialName[0] == '\0')) throw new ArgumentException(SR.Format_StringZeroLength, nameof(partialName)); try { return Load(partialName); } catch (FileNotFoundException) { return null; } } } }