/// <summary> /// Evaluates the node, using the variables provided in the <paramref name="Variables"/> collection. /// </summary> /// <param name="Variables">Variables collection.</param> /// <returns>Result.</returns> public override IElement Evaluate(Variables Variables) { IElement E = this.op.Evaluate(Variables); object Object = E.AssociatedObjectValue; Type T, PT; IElement[] Arguments = null; object[] ParameterValues; bool[] Extend; object Value; object Instance; int i; bool DoExtend = false; if (Object is null && this.nullCheck) { return(ObjectValue.Null); } T = Object as Type; if (T is null) { T = Object.GetType(); Instance = Object; } else { Instance = null; } lock (this.synchObject) { if (this.lastType != T) { this.method = null; this.methods = null; this.byReference = null; this.lastType = T; } Arguments = new IElement[this.nrParameters]; for (i = 0; i < this.nrParameters; i++) { Arguments[i] = this.parameters[i].Evaluate(Variables); } if (!(this.method is null)) { if (this.methodParametersTypes.Length != this.nrParameters) { this.method = null; this.methods = null; this.byReference = null; } else { for (i = 0; i < this.methodParametersTypes.Length; i++) { PT = this.methodParametersTypes[i].ParameterType; if (PT.IsByRef && Arguments[i].TryConvertTo(PT.GetElementType(), out Value)) { this.methodArgumentExtensions[i] = false; this.methodArguments[i] = Value; } else if (Arguments[i].TryConvertTo(PT, out Value)) { this.methodArgumentExtensions[i] = false; this.methodArguments[i] = Value; } else { if (Arguments[i].IsScalar) { break; } this.methodArgumentExtensions[i] = true; this.methodArguments[i] = null; DoExtend = true; } } if (i < this.methodParametersTypes.Length) { this.method = null; this.methods = null; this.byReference = null; } } } if (this.method is null) { if (this.methods is null) { this.methods = this.GetMethods(T); } List <KeyValuePair <string, int> > ByRef = null; VariableReference Ref; ParameterValues = null; Extend = null; foreach (KeyValuePair <MethodInfo, ParameterInfo[]> P in this.methods) { DoExtend = false; if (Instance is null) { if (!P.Key.IsStatic) { continue; } } else { if (P.Key.IsStatic) { continue; } } for (i = 0; i < this.nrParameters; i++) { PT = P.Value[i].ParameterType; if (PT.IsByRef && Arguments[i].TryConvertTo(PT.GetElementType(), out Value)) { if (ParameterValues is null) { Extend = new bool[this.nrParameters]; ParameterValues = new object[this.nrParameters]; } Extend[i] = false; ParameterValues[i] = Value; if (ByRef is null) { ByRef = new List <KeyValuePair <string, int> >(); } if (!((Ref = this.parameters[i] as VariableReference) is null)) { ByRef.Add(new KeyValuePair <string, int>(Ref.VariableName, i)); } else { ByRef.Add(new KeyValuePair <string, int>(null, i)); } } else if (Arguments[i].TryConvertTo(PT, out Value)) { if (ParameterValues is null) { Extend = new bool[this.nrParameters]; ParameterValues = new object[this.nrParameters]; } Extend[i] = false; ParameterValues[i] = Value; } else { if (Arguments[i].IsScalar) { break; } if (Extend is null) { Extend = new bool[this.nrParameters]; ParameterValues = new object[this.nrParameters]; } Extend[i] = true; ParameterValues[i] = null; DoExtend = true; } } if (i < this.nrParameters) { ByRef?.Clear(); continue; } this.method = P.Key; this.methodParametersTypes = P.Value; this.methodArguments = ParameterValues; this.methodArgumentExtensions = Extend; if (!(ByRef is null) && ByRef.Count > 0) { this.byReference = ByRef.ToArray(); }
/// <summary> /// Evaluates the node, using the variables provided in the <paramref name="Variables"/> collection. /// </summary> /// <param name="Variables">Variables collection.</param> /// <returns>Result.</returns> public override IElement Evaluate(Variables Variables) { IElement E = this.op.Evaluate(Variables); object Object = E.AssociatedObjectValue; Type T, PT; IElement[] Arguments = null; object[] ParameterValues; bool[] Extend; object Value; object Instance; int i; bool DoExtend = false; T = Object as Type; if (T == null) { T = Object.GetType(); Instance = Object; } else { Instance = null; } lock (this.synchObject) { if (this.lastType != T) { this.method = null; this.methods = null; this.byReference = null; this.lastType = T; } Arguments = new IElement[this.nrParameters]; for (i = 0; i < this.nrParameters; i++) { Arguments[i] = this.parameters[i].Evaluate(Variables); } if (this.method != null) { if (this.methodParametersTypes.Length != this.nrParameters) { this.method = null; this.methods = null; this.byReference = null; } else { for (i = 0; i < this.methodParametersTypes.Length; i++) { PT = this.methodParametersTypes[i].ParameterType; if (PT.IsByRef && Arguments[i].TryConvertTo(PT.GetElementType(), out Value)) { this.methodArgumentExtensions[i] = false; this.methodArguments[i] = Value; } else if (Arguments[i].TryConvertTo(PT, out Value)) { this.methodArgumentExtensions[i] = false; this.methodArguments[i] = Value; } else { if (Arguments[i].IsScalar) { break; } this.methodArgumentExtensions[i] = true; this.methodArguments[i] = null; DoExtend = true; } } if (i < this.methodParametersTypes.Length) { this.method = null; this.methods = null; this.byReference = null; } } } if (this.method == null) { if (this.methods == null) { this.methods = this.GetMethods(T); } List <KeyValuePair <string, int> > ByRef = null; VariableReference Ref; ParameterValues = null; Extend = null; foreach (KeyValuePair <MethodInfo, ParameterInfo[]> P in this.methods) { DoExtend = false; if (Instance == null) { if (!P.Key.IsStatic) { continue; } } else { if (P.Key.IsStatic) { continue; } } for (i = 0; i < this.nrParameters; i++) { PT = P.Value[i].ParameterType; if (PT.IsByRef && Arguments[i].TryConvertTo(PT.GetElementType(), out Value)) { if (ParameterValues == null) { Extend = new bool[this.nrParameters]; ParameterValues = new object[this.nrParameters]; } Extend[i] = false; ParameterValues[i] = Value; if (ByRef == null) { ByRef = new List <KeyValuePair <string, int> >(); } if ((Ref = this.parameters[i] as VariableReference) != null) { ByRef.Add(new KeyValuePair <string, int>(Ref.VariableName, i)); } else { ByRef.Add(new KeyValuePair <string, int>(null, i)); } } else if (Arguments[i].TryConvertTo(PT, out Value)) { if (ParameterValues == null) { Extend = new bool[this.nrParameters]; ParameterValues = new object[this.nrParameters]; } Extend[i] = false; ParameterValues[i] = Value; } else { if (Arguments[i].IsScalar) { break; } if (Extend == null) { Extend = new bool[this.nrParameters]; ParameterValues = new object[this.nrParameters]; } Extend[i] = true; ParameterValues[i] = null; DoExtend = true; } } if (i < this.nrParameters) { if (ByRef != null) { ByRef.Clear(); } continue; } this.method = P.Key; this.methodParametersTypes = P.Value; this.methodArguments = ParameterValues; this.methodArgumentExtensions = Extend; if (ByRef != null && ByRef.Count > 0) { this.byReference = ByRef.ToArray(); } else { this.byReference = null; } break; } if (this.method == null) { throw new ScriptRuntimeException("Invalid number or type of parameters.", this); } } } if (DoExtend) { if (this.byReference != null) { throw new ScriptException("Canonical extensions of method calls having reference type arguments not supported."); // TODO } return(this.EvaluateCanonical(Instance, this.method, this.methodParametersTypes, Arguments, this.methodArguments, this.methodArgumentExtensions)); } else { Value = this.method.Invoke(Instance, this.methodArguments); if (this.byReference != null) { int j, c = this.byReference.Length; string s; for (i = 0; i < c; i++) { j = this.byReference[i].Value; if (string.IsNullOrEmpty(s = this.byReference[i].Key)) { Dictionary <string, IElement> Found = new Dictionary <string, IElement>(); this.parameters[j].PatternMatch(Expression.Encapsulate(this.methodArguments[j]), Found); foreach (KeyValuePair <string, IElement> P in Found) { Variables[P.Key] = P.Value; } } else { Variables[s] = this.methodArguments[j]; } } } return(Expression.Encapsulate(Value)); } }