File: System\Linq\Expressions\Compiler\AssemblyGen.cs
Web Access
Project: src\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj (System.Linq.Expressions)
// 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.CodeAnalysis;
using System.Dynamic.Utils;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
 
namespace System.Linq.Expressions.Compiler
{
    [RequiresDynamicCode("Assembly generation requires dynamic code generation.")]
    internal sealed class AssemblyGen
    {
        private static AssemblyGen? s_assembly;
 
        private readonly ModuleBuilder _myModule;
 
        private int _index;
 
        private static AssemblyGen Assembly
        {
            get
            {
                if (s_assembly == null)
                {
                    Interlocked.CompareExchange(ref s_assembly, new AssemblyGen(), comparand: null);
                }
                return s_assembly;
            }
        }
 
        private AssemblyGen()
        {
            var name = new AssemblyName("Snippets");
 
            AssemblyBuilder myAssembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
            _myModule = myAssembly.DefineDynamicModule(name.Name!);
        }
 
        private TypeBuilder DefineType(string name, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type parent, TypeAttributes attr)
        {
            ArgumentNullException.ThrowIfNull(name);
            ArgumentNullException.ThrowIfNull(parent);
 
            StringBuilder sb = new StringBuilder(name);
 
            int index = Interlocked.Increment(ref _index);
            sb.Append('$');
            sb.Append(index);
 
            // An unhandled Exception: System.Runtime.InteropServices.COMException (0x80131130): Record not found on lookup.
            // is thrown if there is any of the characters []*&+,\ in the type name and a method defined on the type is called.
            sb.Replace('+', '_').Replace('[', '_').Replace(']', '_').Replace('*', '_').Replace('&', '_').Replace(',', '_').Replace('\\', '_');
 
            name = sb.ToString();
 
            return _myModule.DefineType(name, attr, parent);
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
            Justification = "MulticastDelegate has a ctor with RequiresUnreferencedCode, but the generated derived type doesn't reference this ctor, so this is trim compatible.")]
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2111:ReflectionToDynamicallyAccessedMembers",
            Justification = "MulticastDelegate and Delegate have multiple methods with DynamicallyAccessedMembers annotations. But the generated code" +
            "in this case will not call any of them (it only defines a .ctor and Invoke method both of which are runtime implemented.")]
        internal static TypeBuilder DefineDelegateType(string name)
        {
            return Assembly.DefineType(
                name,
                typeof(MulticastDelegate),
                TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass
            );
        }
    }
}