//
        // Helper for the V1/V1.1 Delegate.CreateDelegate() api. These apis take method names rather than MethodInfo and only expect to create open static delegates
        // or closed instance delegates. For backward compatibility, they don't allow relaxed signature matching (which could make the choice of target method ambiguous.)
        //
        private static RuntimeMethodInfo LookupMethodForCreateDelegate(RuntimeTypeInfo runtimeDelegateType, RuntimeTypeInfo containingType, string method, bool isStatic, bool ignoreCase)
        {
            Debug.Assert(runtimeDelegateType.IsDelegate);

            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.ExactBinding;

            if (isStatic)
            {
                bindingFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
            }
            else
            {
                bindingFlags |= BindingFlags.Instance;
            }
            if (ignoreCase)
            {
                bindingFlags |= BindingFlags.IgnoreCase;
            }
            RuntimeMethodInfo invokeMethod = runtimeDelegateType.GetInvokeMethod();

            ParameterInfo[] parameters    = invokeMethod.GetParametersNoCopy();
            int             numParameters = parameters.Length;

            Type[] parameterTypes = new Type[numParameters];
            for (int i = 0; i < numParameters; i++)
            {
                parameterTypes[i] = parameters[i].ParameterType;
            }
            MethodInfo methodInfo = containingType.GetMethod(method, bindingFlags, null, parameterTypes, null);

            if (methodInfo == null)
            {
                return(null);
            }

            if (!methodInfo.ReturnType.Equals(invokeMethod.ReturnType))
            {
                return(null);
            }

            return((RuntimeMethodInfo)methodInfo); // This cast is safe since we already verified that containingType is runtime implemented.
        }
Exemple #2
0
        //
        // Helper for the V1/V1.1 Delegate.CreateDelegate() api. These apis take method names rather than MethodInfo and only expect to create open static delegates
        // or closed instance delegates. For backward compatibility, they don't allow relaxed signature matching (which could make the choice of target method ambiguous.)
        //
        private static RuntimeMethodInfo LookupMethodForCreateDelegate(RuntimeTypeInfo runtimeDelegateType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] RuntimeTypeInfo containingType, string method, bool isStatic, bool ignoreCase)
        {
            Debug.Assert(runtimeDelegateType.IsDelegate);

            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.ExactBinding;

            if (isStatic)
            {
                bindingFlags |= BindingFlags.Static;
            }
            else
            {
                bindingFlags |= BindingFlags.Instance | BindingFlags.DeclaredOnly;
            }
            if (ignoreCase)
            {
                bindingFlags |= BindingFlags.IgnoreCase;
            }
            RuntimeMethodInfo invokeMethod = runtimeDelegateType.GetInvokeMethod();

            ParameterInfo[] parameters    = invokeMethod.GetParametersNoCopy();
            int             numParameters = parameters.Length;

            Type[] parameterTypes = new Type[numParameters];
            for (int i = 0; i < numParameters; i++)
            {
                parameterTypes[i] = parameters[i].ParameterType;
            }

            while (containingType != null)
            {
                MethodInfo?methodInfo = containingType.GetMethod(method, 0, bindingFlags, null, parameterTypes, null);
                if (methodInfo != null && methodInfo.ReturnType.Equals(invokeMethod.ReturnType))
                {
                    return((RuntimeMethodInfo)methodInfo); // This cast is safe since we already verified that containingType is runtime implemented.
                }
#pragma warning disable IL2072                             // https://github.com/dotnet/linker/issues/2673
                containingType = (RuntimeTypeInfo)(containingType.BaseType);
#pragma warning restore
            }
            return(null);
        }
        public sealed override DynamicInvokeInfo GetDelegateDynamicInvokeInfo(Type type)
        {
            RuntimeTypeInfo runtimeType = type.CastToRuntimeTypeInfo();

            DynamicInvokeInfo?info = runtimeType.GenericCache as DynamicInvokeInfo;

            if (info != null)
            {
                return(info);
            }

            RuntimeMethodInfo invokeMethod = runtimeType.GetInvokeMethod();

            MethodInvoker methodInvoker = invokeMethod.MethodInvoker;
            IntPtr        invokeThunk   = ReflectionCoreExecution.ExecutionDomain.ExecutionEnvironment.GetDynamicInvokeThunk(methodInvoker);

            info = new DynamicInvokeInfo(invokeMethod, invokeThunk);
            runtimeType.GenericCache = info;
            return(info);
        }
        /// <summary>
        /// Common CreateDelegate worker. NOTE: If the method signature is not compatible, this method returns null rather than throwing an ArgumentException.
        /// This is needed to support the api overloads that have a "throwOnBindFailure" parameter.
        /// </summary>
        internal Delegate CreateDelegateNoThrowOnBindFailure(RuntimeTypeInfo runtimeDelegateType, Object target, bool allowClosed)
        {
            Debug.Assert(runtimeDelegateType.IsDelegate);

            ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
            MethodInfo           invokeMethod         = runtimeDelegateType.GetInvokeMethod();

            // Make sure the return type is assignment-compatible.
            Type expectedReturnType = ReturnParameter.ParameterType;
            Type actualReturnType   = invokeMethod.ReturnParameter.ParameterType;

            if (!IsAssignableFrom(executionEnvironment, actualReturnType, expectedReturnType))
            {
                return(null);
            }
            if (expectedReturnType.IsValueType && !actualReturnType.IsValueType)
            {
                // For value type returning methods, conversions between enums and primitives are allowed (and screened by the above call to IsAssignableFrom)
                // but conversions to Object or interfaces implemented by the value type are not.
                return(null);
            }

            IList <ParameterInfo>       delegateParameters          = invokeMethod.GetParametersNoCopy();
            IList <ParameterInfo>       targetParameters            = this.GetParametersNoCopy();
            IEnumerator <ParameterInfo> delegateParameterEnumerator = delegateParameters.GetEnumerator();
            IEnumerator <ParameterInfo> targetParameterEnumerator   = targetParameters.GetEnumerator();

            bool isStatic = this.IsStatic;
            bool isOpen;

            if (isStatic)
            {
                if (delegateParameters.Count == targetParameters.Count)
                {
                    // Open static: This is the "typical" case of calling a static method.
                    isOpen = true;
                    if (target != null)
                    {
                        return(null);
                    }
                }
                else
                {
                    // Closed static: This is the "weird" v2.0 case where the delegate is closed over the target method's first parameter.
                    //   (it make some kinda sense if you think of extension methods.)
                    if (!allowClosed)
                    {
                        return(null);
                    }
                    isOpen = false;
                    if (!targetParameterEnumerator.MoveNext())
                    {
                        return(null);
                    }
                    if (target != null && !IsAssignableFrom(executionEnvironment, targetParameterEnumerator.Current.ParameterType, target.GetType()))
                    {
                        return(null);
                    }
                }
            }
            else
            {
                if (delegateParameters.Count == targetParameters.Count)
                {
                    // Closed instance: This is the "typical" case of invoking an instance method.
                    isOpen = false;
                    if (!allowClosed)
                    {
                        return(null);
                    }
                    if (target != null && !IsAssignableFrom(executionEnvironment, this.DeclaringType, target.GetType()))
                    {
                        return(null);
                    }
                }
                else
                {
                    // Open instance: This is the "weird" v2.0 case where the delegate has a leading extra parameter that's assignable to the target method's
                    // declaring type.
                    if (!delegateParameterEnumerator.MoveNext())
                    {
                        return(null);
                    }
                    isOpen = true;
                    Type firstParameterOfMethodType = this.DeclaringType;
                    if (firstParameterOfMethodType.IsValueType)
                    {
                        firstParameterOfMethodType = firstParameterOfMethodType.MakeByRefType();
                    }

                    if (!IsAssignableFrom(executionEnvironment, firstParameterOfMethodType, delegateParameterEnumerator.Current.ParameterType))
                    {
                        return(null);
                    }
                    if (target != null)
                    {
                        return(null);
                    }
                }
            }

            // Verify that the parameters that the delegate and method have in common are assignment-compatible.
            while (delegateParameterEnumerator.MoveNext())
            {
                if (!targetParameterEnumerator.MoveNext())
                {
                    return(null);
                }
                if (!IsAssignableFrom(executionEnvironment, targetParameterEnumerator.Current.ParameterType, delegateParameterEnumerator.Current.ParameterType))
                {
                    return(null);
                }
            }
            if (targetParameterEnumerator.MoveNext())
            {
                return(null);
            }

            return(CreateDelegateWithoutSignatureValidation(runtimeDelegateType, target, isStatic: isStatic, isOpen: isOpen));
        }