public async Task <JObject> Resolve(InvocationExpressionSyntax method, Dictionary <string, JObject> memberAccessValues, CancellationToken token) { var methodName = ""; int isTryingLinq = 0; try { JObject rootObject = null; var expr = method.Expression; if (expr is MemberAccessExpressionSyntax) { var memberAccessExpressionSyntax = expr as MemberAccessExpressionSyntax; rootObject = await Resolve(memberAccessExpressionSyntax.Expression.ToString(), token); methodName = memberAccessExpressionSyntax.Name.ToString(); } else if (expr is IdentifierNameSyntax) { if (scopeCache.ObjectFields.TryGetValue("this", out JObject valueRet)) { rootObject = await GetValueFromObject(valueRet, token); methodName = expr.ToString(); } } if (rootObject != null) { DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId); var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], methodName, token); var className = await sdbHelper.GetTypeNameOriginal(sessionId, typeIds[0], token); if (methodId == 0) //try to search on System.Linq.Enumerable { if (linqTypeId == -1) { linqTypeId = await sdbHelper.GetTypeByName(sessionId, "System.Linq.Enumerable", token); } methodId = await sdbHelper.GetMethodIdByName(sessionId, linqTypeId, methodName, token); if (methodId != 0) { foreach (var typeId in typeIds) { var genericTypeArgs = await sdbHelper.GetTypeParamsOrArgsForGenericType(sessionId, typeId, token); if (genericTypeArgs.Count > 0) { isTryingLinq = 1; methodId = await sdbHelper.MakeGenericMethod(sessionId, methodId, genericTypeArgs, token); break; } } } } if (methodId == 0) { var typeName = await sdbHelper.GetTypeName(sessionId, typeIds[0], token); throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); } var commandParamsObj = new MemoryStream(); var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); if (isTryingLinq == 0) { commandParamsObjWriter.WriteObj(objectId, sdbHelper); } if (method.ArgumentList != null) { commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq); if (isTryingLinq == 1) { commandParamsObjWriter.WriteObj(objectId, sdbHelper); } foreach (var arg in method.ArgumentList.Arguments) { if (arg.Expression is LiteralExpressionSyntax) { if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, sdbHelper, token)) { return(null); } } if (arg.Expression is IdentifierNameSyntax) { var argParm = arg.Expression as IdentifierNameSyntax; if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], sdbHelper, token)) { return(null); } } } var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); return(await GetValueFromObject(retMethod, token)); } } return(null); } catch (Exception) { throw new Exception($"Unable to evaluate method '{methodName}'"); } }
public async Task <JObject> Resolve(ElementAccessExpressionSyntax elementAccess, Dictionary <string, JObject> memberAccessValues, JObject indexObject, CancellationToken token) { try { JObject rootObject = null; string elementAccessStrExpression = elementAccess.Expression.ToString(); rootObject = await Resolve(elementAccessStrExpression, token); if (rootObject == null) { rootObject = indexObject; indexObject = null; } if (rootObject != null) { string elementIdxStr; int elementIdx = 0; // x[1] or x[a] or x[a.b] if (indexObject == null) { if (elementAccess.ArgumentList != null) { var commandParamsObj = new MemoryStream(); var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); foreach (var arg in elementAccess.ArgumentList.Arguments) { // e.g. x[1] if (arg.Expression is LiteralExpressionSyntax) { var argParm = arg.Expression as LiteralExpressionSyntax; elementIdxStr = argParm.ToString(); int.TryParse(elementIdxStr, out elementIdx); } // e.g. x[a] or x[a.b] if (arg.Expression is IdentifierNameSyntax) { var argParm = arg.Expression as IdentifierNameSyntax; // x[a.b] memberAccessValues.TryGetValue(argParm.Identifier.Text, out indexObject); // x[a] if (indexObject == null) { indexObject = await Resolve(argParm.Identifier.Text, token); } elementIdxStr = indexObject["value"].ToString(); int.TryParse(elementIdxStr, out elementIdx); } } } } // e.g. x[a[0]], x[a[b[1]]] etc. else { elementIdxStr = indexObject["value"].ToString(); int.TryParse(elementIdxStr, out elementIdx); } if (elementIdx >= 0) { DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId); switch (objectId.Scheme) { case "array": rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(objectId.Value), token); return((JObject)rootObject["value"][elementIdx]["value"]); case "object": var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], "ToArray", token); var commandParamsObj = new MemoryStream(); var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); commandParamsObjWriter.WriteObj(objectId, sdbHelper); var toArrayRetMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, elementAccess.Expression.ToString(), token); rootObject = await GetValueFromObject(toArrayRetMethod, token); DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId arrayObjectId); rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(arrayObjectId.Value), token); return((JObject)rootObject["value"][elementIdx]["value"]); default: throw new InvalidOperationException($"Cannot apply indexing with [] to an expression of type '{objectId.Scheme}'"); } } } return(null); } catch (Exception ex) { var e = ex; throw new Exception($"Unable to evaluate method '{elementAccess}'"); } }