Esempio n. 1
0
        /// <inheritdoc />
        protected override object ExecuteToken(ScriptContext context)
        {
            object host = hosttoken.Execute(context);

            if (host == null)
            {
                throw new ScriptRuntimeException($"'{hosttoken}' results in null", this);
            }

            if (host is IExternalMethod externmethod && MethodName.ToLower() == "invoke")
            {
                try {
                    return(externmethod.Invoke(context.Arguments, Parameters.Select(a => a.Execute(context)).ToArray()));
                }
                catch (Exception e) {
                    throw new ScriptRuntimeException($"Error calling external method '{externmethod}'", this, e);
                }
            }

            MethodInfo[] methods = host.GetType().GetMethods().Where(m => m.Name.ToLower() == methodname && MethodOperations.MatchesParameterCount(m, parameters)).ToArray();

            object[] parametervalues = parameters.Select(p => p.Execute(context)).ToArray();

            List <ReferenceParameter> references = new List <ReferenceParameter>();

            for (int i = 0; i < parameters.Length; ++i)
            {
                if (!(parameters[i] is Reference r))
                {
                    continue;
                }
                references.Add(new ReferenceParameter(i, r));
            }

            Tuple <MethodInfo, int>[] evaluation = methods.Select(m => MethodOperations.GetMethodMatchValue(m, parametervalues)).Where(e => e.Item2 >= 0).OrderBy(m => m.Item2).ToArray();
            if (evaluation.Length > 0)
            {
                return(MethodOperations.CallMethod(this, host, evaluation[0].Item1, parametervalues, context, references));
            }

            if (extensions != null)
            {
                Type extensionbase = host.GetType();
                while (extensionbase != null)
                {
                    Type lookuptype = extensionbase;
                    if (lookuptype.IsGenericType)
                    {
                        lookuptype = lookuptype.GetGenericTypeDefinition();
                    }

                    methods    = extensions.GetExtensions(lookuptype).Where(m => m.Name.ToLower() == methodname && MethodOperations.MatchesParameterCount(m, parameters, true)).ToArray();
                    evaluation = methods.Select(m => MethodOperations.GetMethodMatchValue(m, parametervalues, true)).OrderBy(m => m.Item2).ToArray();
                    if (evaluation.Length > 0)
                    {
                        MethodInfo method = evaluation[0].Item1;
                        if (method.IsGenericMethodDefinition)
                        {
                            method = method.MakeGenericMethod(extensionbase.GetGenericArguments());
                        }

                        return(MethodOperations.CallMethod(this, host, method, parametervalues, context, references, true));
                    }

                    if (extensionbase == typeof(object))
                    {
                        break;
                    }
                    extensionbase = extensionbase.BaseType;
                }


                foreach (Type interfacetype in host.GetType().GetInterfaces().OrderBy(i => i.IsGenericType ? 0 : 1))
                {
                    Type lookuptype = interfacetype;
                    if (lookuptype.IsGenericType)
                    {
                        lookuptype = lookuptype.GetGenericTypeDefinition();
                    }

                    methods    = extensions.GetExtensions(lookuptype).Where(m => m.Name.ToLower() == methodname && MethodOperations.MatchesParameterCount(m, parameters, true)).ToArray();
                    evaluation = methods.Select(m => MethodOperations.GetMethodMatchValue(m, parametervalues, true)).OrderBy(m => m.Item2).ToArray();
                    if (evaluation.Length > 0)
                    {
                        MethodInfo method = evaluation[0].Item1;
                        if (method.IsGenericMethodDefinition)
                        {
                            method = method.MakeGenericMethod(interfacetype.GetGenericArguments());
                        }

                        return(MethodOperations.CallMethod(this, host, method, parametervalues, context, references, true));
                    }
                }
            }

            throw new ScriptRuntimeException($"Method '{methodname}' matching the parameters '({string.Join(",", parametervalues)})' not found on type {host.GetType().Name}", this);
        }