| File: System\Linq\Expressions\Compiler\DelegateHelpers.cs | Web Access |
| Project: src\runtime\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.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Dynamic.Utils; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; namespace System.Linq.Expressions.Compiler { internal static partial class DelegateHelpers { /// <summary> /// Finds a delegate type for a CallSite using the types in the ReadOnlyCollection of Expression. /// /// We take the read-only collection of Expression explicitly to avoid allocating memory (an array /// of types) on lookup of delegate types. /// </summary> [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)] internal static Type MakeCallSiteDelegate(ReadOnlyCollection<Expression> types, Type returnType) { lock (_DelegateCache) { TypeInfo curTypeInfo = _DelegateCache; // CallSite curTypeInfo = NextTypeInfo(typeof(CallSite), curTypeInfo); // arguments for (int i = 0; i < types.Count; i++) { curTypeInfo = NextTypeInfo(types[i].Type, curTypeInfo); } // return type curTypeInfo = NextTypeInfo(returnType, curTypeInfo); // see if we have the delegate already if (curTypeInfo.DelegateType == null) { curTypeInfo.MakeDelegateType(returnType, types); } return curTypeInfo.DelegateType!; } } /// <summary> /// Finds a delegate type for a CallSite using the MetaObject array. /// /// We take the array of MetaObject explicitly to avoid allocating memory (an array of types) on /// lookup of delegate types. /// </summary> [RequiresDynamicCode(Expression.DelegateCreationRequiresDynamicCode)] internal static Type MakeDeferredSiteDelegate(DynamicMetaObject[] args, Type returnType) { lock (_DelegateCache) { TypeInfo curTypeInfo = _DelegateCache; // CallSite curTypeInfo = NextTypeInfo(typeof(CallSite), curTypeInfo); // arguments for (int i = 0; i < args.Length; i++) { DynamicMetaObject mo = args[i]; Type paramType = mo.Expression.Type; if (IsByRef(mo)) { paramType = paramType.MakeByRefType(); } curTypeInfo = NextTypeInfo(paramType, curTypeInfo); } // return type curTypeInfo = NextTypeInfo(returnType, curTypeInfo); // see if we have the delegate already if (curTypeInfo.DelegateType == null) { // nope, go ahead and create it and spend the // cost of creating the array. Type[] paramTypes = new Type[args.Length + 2]; paramTypes[0] = typeof(CallSite); paramTypes[paramTypes.Length - 1] = returnType; for (int i = 0; i < args.Length; i++) { DynamicMetaObject mo = args[i]; Type paramType = mo.Expression.Type; if (IsByRef(mo)) { paramType = paramType.MakeByRefType(); } paramTypes[i + 1] = paramType; } curTypeInfo.DelegateType = MakeNewDelegate(paramTypes); } return curTypeInfo.DelegateType; } } private static bool IsByRef(DynamicMetaObject mo) { return mo.Expression is ParameterExpression pe && pe.IsByRef; } private static System.Reflection.TypeInfo MakeNewCustomDelegate(Type[] types) { if (RuntimeFeature.IsDynamicCodeSupported) { Type returnType = types[types.Length - 1]; Type[] parameters = types.RemoveLast(); Type[] delegateCtorSignature = { typeof(object), typeof(IntPtr) }; const MethodAttributes ctorAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; const MethodImplAttributes implAttributes = MethodImplAttributes.Runtime | MethodImplAttributes.Managed; const MethodAttributes invokeAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; TypeBuilder builder = AssemblyGen.DefineDelegateType("Delegate" + types.Length); builder.DefineConstructor(ctorAttributes, CallingConventions.Standard, delegateCtorSignature).SetImplementationFlags(implAttributes); builder.DefineMethod("Invoke", invokeAttributes, returnType, parameters).SetImplementationFlags(implAttributes); return builder.CreateTypeInfo(); } else { throw new PlatformNotSupportedException(); } } } }