예제 #1
0
        public object Invoke(MethodBase method, object target, object[] arguments, MethodBase caller, BindingFlags invokeAttr = BindingFlags.Default, Binder binder = null, CultureInfo culture = null)
        {
            if (binder != null)
            {
                throw new NotSupportedException();
            }

            if (method.DeclaringType.ContainsGenericParameters)
            {
                throw new Exception($"Attempted to call method {method} on open generic type {method.DeclaringType}.");
            }

            if ((method as MethodInfo)?.ContainsGenericParameters ?? false)
            {
                throw new Exception($"Attempted to call open generic method {method}.");
            }

            if (method.IsConstructor && !method.IsStatic && (target == null))
            {
                return(InvokeConstructorForNewObject((ConstructorInfo)method, arguments, caller));
            }

            object result;

            if (TryInvokeSpecialMethod(method, arguments, caller, out result))
            {
                return(result);
            }

            if (!method.IsStatic)
            {
                if (target == null)
                {
                    throw new NullReferenceException($"Attempted to call instance method {method.Name} on null reference.");
                }

                var custom = target as ICustomInvoker;
                if (custom != null)
                {
                    return(custom.Invoke(method, arguments, invokeAttr, binder, culture));
                }
            }

            if (!(method is IInterpretedMethodBase))
            {
                var unwrapped = ObjectWrapper.UnwrapIfRequired(target);
                if (!(unwrapped is INonRuntimeObject))
                {
                    if (method.DeclaringType.IsInterface && !unwrapped.GetType().IsArray)
                    {
                        method = GetMatchingMethod(unwrapped.GetType(), (MethodInfo)method);
                    }

                    return(method.Invoke(unwrapped, invokeAttr, binder, arguments, culture));
                }
            }

            if (!method.IsStatic && !method.IsConstructor)
            {
                var targetType = TypeSupport.GetTypeOf(target);
                if (method.DeclaringType != targetType)
                {
                    method = GetMatchingMethod(targetType, (MethodInfo)method);
                }
            }

            var interpreted = method as IInterpretedMethodBase;

            if (interpreted == null)
            {
                throw new Exception($"Cannot invoke runtime method {method} on non-runtime instance {target}.");
            }

            return(_interpreter.InterpretCall(
                       method.DeclaringType.GetGenericArguments(),
                       (MethodBase)interpreted, (MethodDefinition)interpreted.InvokableDefinition,
                       method.GetGenericArguments(),
                       target, arguments
                       ));
        }