예제 #1
0
        /// <summary>
        ///     Smart emission for Call methods.
        /// </summary>
        /// <param name="il">Self.</param>
        /// <param name="methodInfo">Static, virtual, instance method.</param>
        /// <param name="funcs">List of methods to prepare parameters in stack.</param>
        /// <returns>Self.</returns>
        public static ILEmitter CallMethod(
            this ILEmitter il,
            MethodInfo methodInfo,
            params ILEmitterFunc[] funcs)
        {
            var owner = methodInfo.DeclaringType;

            if (owner == typeof(ValueType))
            {
                owner = methodInfo.ReflectedType; // todo: 0. test
            }

            if (owner == null)
            {
                throw new InvalidOperationException(
                          $"It's not expected that {methodInfo.DisplayName()} doesn't have a declaring type.");
            }

            if (methodInfo.IsGenericMethodDefinition)
            {
                throw new InvalidOperationException(
                          $"Generic method {methodInfo.DisplayName()} is not initialized.");
            }

            // if the method belongs to Enum type, them it should be called as virtual and with constrained prefix
            // https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.constrained
            //var isEnum = owner.IsAssignableFrom(typeof(Enum));
            //if (isEnum) {
            //    Constrained(owner); // todo: 0. test
            //}

            return(methodInfo.IsStatic || owner.IsValueType || owner.IsSealed || !methodInfo.IsVirtual // todo: 0. test
                ? il.Call(methodInfo, funcs)
                : il.Callvirt(methodInfo, funcs));
        }