public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (expression is ConstantExpression constantExpression) { var parameterKey = parameters.AddNext(constantExpression.Value); result = $"args.{parameterKey}"; return(true); } result = default; return(false); }
public bool TryProcess(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { if (methodCallExpression == null) { throw new ArgumentNullException(nameof(methodCallExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (methodCallExpression.Method.DeclaringType != typeof(Enumerable)) { result = default; return(false); } foreach (var processor in expressionProcessors) { if (processor.TryProcess(methodCallExpression, parameters, out result)) { return(true); } } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var lambdaExpression = expression as LambdaExpression; if (lambdaExpression == null) { result = default; return(false); } var parameterList = string.Join(", ", lambdaExpression.Parameters.Select(p => p.Name)); var body = _expressionProcessorPipeline.ProcessExpression(lambdaExpression.Body, parameters); // TODO: Consider whether "return" is always correct (technically we can return void stuff in JS but what if result = $"function({parameterList}) {{ return {body}; }}"; return(true); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (expression.NodeType != ExpressionType.MemberAccess) { result = default; return(false); } foreach (var processor in expressionProcessors) { if (processor.TryProcess((MemberExpression)expression, parameters, out result)) { return(true); } } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (expression is ConditionalExpression conditionalExpression) { var test = _expressionProcessorPipeline.ProcessExpression(conditionalExpression.Test, parameters); var ifTrue = _expressionProcessorPipeline.ProcessExpression(conditionalExpression.IfTrue, parameters); var ifFalse = _expressionProcessorPipeline.ProcessExpression(conditionalExpression.IfFalse, parameters); result = $"({test} ? {ifTrue} : {ifFalse})"; return(true); } result = default; return(false); }
public bool TryProcess(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { if (methodCallExpression == null) { throw new ArgumentNullException(nameof(methodCallExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (TryProcessPredicatelessAny(methodCallExpression, parameters, out result)) { return(true); } if (TryProcessPredicatedAny(methodCallExpression, parameters, out result)) { return(true); } result = default; return(false); }
public bool TryProcess(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { if (methodCallExpression == null) { throw new ArgumentNullException(nameof(methodCallExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (!integralTypes.Contains(methodCallExpression.Method.DeclaringType)) { result = default; return(false); } if (methodCallExpression.Method.Name == ToStringMethodName) { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Object, parameters); result = $"{ownerExpressionString}.toString()"; return(true); } result = default; return(false); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // TODO: Tests if (memberExpression.Member is PropertyInfo propertyInfo) { if (IsDictionaryCountAccess(propertyInfo)) { // Dictionaries are mapped to object literals based on their keys when they are serialized to JSON, // so we can't use the .length as we would with a regular collection. But there are as many items // in a dictionary as there are keys, so we need find the number of keys to resolve the expression. var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); // TODO: Check whether RavenDB provides a magic property for Dictionary key collections. result = $"Object.keys({ownerExpressionString}).length"; return(true); } if (IsDictionaryKeysCollectionCountAccess(memberExpression, propertyInfo)) { // We need to navigate one level further up (i.e. doc.MyDictionary.Keys becomes doc.MyDictionary) // because dictionaries are mapped to object literals with the respective keys when they become // JSON, so the Keys segment becomes invalid. var parentMemberExpression = ((MemberExpression)memberExpression.Expression).Expression; var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(parentMemberExpression, parameters); // TODO: Check whether RavenDB provides a magic property for Dictionary key collections. result = $"Object.keys({ownerExpressionString}).length"; return(true); } if (IsDictionaryValuesCollectionCountAccess(memberExpression, propertyInfo)) { // We need to navigate one level further up (i.e. doc.MyDictionary.Values becomes doc.MyDictionary) // because dictionaries are mapped to object literals with the respective keys when they become // JSON, so the Values segment becomes invalid. var parentMemberExpression = ((MemberExpression)memberExpression.Expression).Expression; var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(parentMemberExpression, parameters); // TODO: Check whether RavenDB provides a magic property for Dictionary value collections. result = $"Object.values({ownerExpressionString}).length"; return(true); } } result = default; return(false); }
private (string script, ScriptParameterDictionary parameters) GetParsedJavaScript(Expression <Func <TestDocument, bool> > expression) { var patchScriptConditionBuilder = PatchScriptConditionBuilderFactory.CreatePatchScriptBodyBuilder(); var parameters = new ScriptParameterDictionary(); var script = patchScriptConditionBuilder.CreateScriptCondition(expression, parameters); return(script, parameters); }
private static void PrintCondition(Expression <Func <TestDocument, bool> > expression) { var originalColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("***********************************************************************************"); Console.WriteLine("C# Expression:"); Console.Write("\t"); Console.WriteLine(expression.ToString()); Console.WriteLine(); var parameters = new ScriptParameterDictionary(); var script = patchScriptConditionBuilder.CreateScriptCondition(expression, parameters); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Created JavaScript expression:"); Console.Write("\t"); Console.WriteLine(script); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.DarkCyan; Console.WriteLine("Parameters:"); foreach (var parameter in parameters) { Console.Write("\t"); string value; if (parameter.Value is string || parameter.Value is char) { value = '"' + parameter.Value.ToString().Replace("\"", "\\\"") + '"'; } else if (parameter.Value == null) { value = "null"; } else { value = parameter.Value.ToString(); } Console.WriteLine($"{parameter.Key}: {value}"); } Console.WriteLine(); Console.ForegroundColor = originalColor; Console.WriteLine(); }
public void BinaryOps_Integers_SubtractAssign() { var memberExpression = LambdaExpression(doc => doc.SomeInt).Body; var constantExpression = Expression.Constant(1); var expression = Expression.SubtractAssign(memberExpression, constantExpression); var parameters = new ScriptParameterDictionary(); var result = expressionProcessorPipeline.ProcessExpression(expression, parameters); Assert.AreEqual( "(doc.SomeInt -= args.__param1)", result); Assert.AreEqual(1, parameters.Count); Assert.AreEqual(1, parameters["__param1"]); }
public string ProcessExpression(Expression expression, ScriptParameterDictionary parameters) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } var simplifiedExpression = _expressionSimplifierPipeline.ProcessExpression(expression); foreach (var processor in _expressionProcessors) { if (processor.TryProcess(simplifiedExpression, parameters, out var result)) { return(result); } } throw new NotSupportedException($"Cannot handle expression of type {expression.GetType().FullName}."); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (memberExpression.Member is PropertyInfo propertyInfo) { var memberOwnerType = propertyInfo.DeclaringType; if (memberOwnerType.IsGenericType) { memberOwnerType = memberOwnerType.GetGenericTypeDefinition(); } if (memberOwnerType == NullableType) { if (propertyInfo.Name == "HasValue") { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"({ownerExpressionString} != null)"; return(true); } if (propertyInfo.Name == "Value") { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"{ownerExpressionString}"; return(true); } } } result = default; return(false); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); // TODO: Consider cases when the property is called differently in the document than in the object model. Check out // Raven.Client.Documents.Linq.LinqPathProvider, maybe that can solve it out-of-the-box. result = $"{ownerExpressionString}.{memberExpression.Member.Name}"; return(true); }
public bool TryProcess(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { if (methodCallExpression == null) { throw new ArgumentNullException(nameof(methodCallExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (methodCallExpression.Method.DeclaringType != StringType) { result = default; return(false); } return(methodCallExpression.Object == null ? TryProcessStaticStringMethodInvocation(methodCallExpression, methodCallExpression.Method, parameters, out result) : TryProcessNonStaticStringMethodInvocation(methodCallExpression, methodCallExpression.Method, parameters, out result)); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (memberExpression.Member is PropertyInfo propertyInfo && propertyInfo == NonStatic_Length) { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"{ownerExpressionString}.length"; return(true); } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (expression is ParameterExpression parameterExpression) { result = parameterExpression.Name; return(true); } result = default; return(false); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // TODO: Tests if (memberExpression.Member is PropertyInfo propertyInfo && IsSpeciallyTreatedCountPropertyAccess(propertyInfo)) { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"{ownerExpressionString}.length"; return(true); } result = default; return(false); }
private bool TryProcessNonStaticStringMethodInvocation(MethodCallExpression methodCallExpression, MethodInfo methodInfo, ScriptParameterDictionary parameters, out string result) { // Methods to implement: // indexof, lastindexof, replace (!must do with "/chars/g", but must escape regex control characters!), split, equals, compareTo var argumentList = new List <string>(); string mappedMethodName = null; if (methodInfo == NonStatic_Contains_Char || methodInfo == NonStatic_Contains_String) { var searchInValue = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Object, parameters); var searchForValueExpression = methodCallExpression.Arguments[0]; var searchForValue = _expressionProcessorPipeline.ProcessExpression(searchForValueExpression, parameters); result = $"({searchInValue}.indexOf({searchForValue}) != -1)"; return(true); } else if (methodInfo == NonStatic_Insert) { var insertIntoValue = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Object, parameters); var indexValueExpression = methodCallExpression.Arguments[0]; var indexValue = _expressionProcessorPipeline.ProcessExpression(indexValueExpression, parameters); var insertValueExpression = methodCallExpression.Arguments[1]; var insertValue = _expressionProcessorPipeline.ProcessExpression(insertValueExpression, parameters); result = $"({insertIntoValue}.substring(0, {indexValue}) + {insertValue} + {insertIntoValue}.substring({indexValue}))"; return(true); } else if (methodInfo == NonStatic_Remove_StartIndex) { mappedMethodName = "substring"; var startIndexValueExpression = methodCallExpression.Arguments[0]; var startIndexValue = _expressionProcessorPipeline.ProcessExpression(startIndexValueExpression, parameters); argumentList.Add("0"); argumentList.Add(startIndexValue); } else if (methodInfo == NonStatic_Remove_StartIndex_Count) { var removeFromValue = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Object, parameters); var firstSegmentStartIndexExpression = methodCallExpression.Arguments[0]; var firstSegmentStartIndexValue = _expressionProcessorPipeline.ProcessExpression(firstSegmentStartIndexExpression, parameters); var countExpression = methodCallExpression.Arguments[1]; var secondSegmentStartIndexExpression = Expression.Add(firstSegmentStartIndexExpression, countExpression); var secondSegmentStartIndexValue = _expressionProcessorPipeline.ProcessExpression(secondSegmentStartIndexExpression, parameters); result = $"({removeFromValue}.substring(0, {firstSegmentStartIndexValue}) + {removeFromValue}.substring({secondSegmentStartIndexValue}))"; return(true); } else if (methodInfo == NonStatic_StartsWith_Value) { mappedMethodName = "startsWith"; var startWithValueExpression = methodCallExpression.Arguments[0]; var startWithValue = _expressionProcessorPipeline.ProcessExpression(startWithValueExpression, parameters); argumentList.Add(startWithValue); } else if (methodInfo == NonStatic_EndsWith_Value) { mappedMethodName = "endsWith"; var startWithValueExpression = methodCallExpression.Arguments[0]; var startWithValue = _expressionProcessorPipeline.ProcessExpression(startWithValueExpression, parameters); argumentList.Add(startWithValue); } else if (methodInfo == NonStatic_PadLeft_TotalWith || methodInfo == NonStatic_PadLeft_TotalWith_PaddingChar) { mappedMethodName = "padStart"; var totalWidthExpression = methodCallExpression.Arguments[0]; var totalWidth = _expressionProcessorPipeline.ProcessExpression(totalWidthExpression, parameters); Expression paddingCharExpression = Expression.Constant(DefaultPaddingChar); if (methodInfo == NonStatic_PadLeft_TotalWith_PaddingChar) { paddingCharExpression = methodCallExpression.Arguments[1]; } var paddingChar = _expressionProcessorPipeline.ProcessExpression(paddingCharExpression, parameters); argumentList.Add(totalWidth); argumentList.Add(paddingChar); } else if (methodInfo == NonStatic_PadRight_TotalWith || methodInfo == NonStatic_PadRight_TotalWith_PaddingChar) { mappedMethodName = "padEnd"; var totalWidthExpression = methodCallExpression.Arguments[0]; var totalWidth = _expressionProcessorPipeline.ProcessExpression(totalWidthExpression, parameters); Expression paddingCharExpression = Expression.Constant(DefaultPaddingChar); if (methodInfo == NonStatic_PadRight_TotalWith_PaddingChar) { paddingCharExpression = methodCallExpression.Arguments[1]; } var paddingChar = _expressionProcessorPipeline.ProcessExpression(paddingCharExpression, parameters); argumentList.Add(totalWidth); argumentList.Add(paddingChar); } else if (methodInfo == NonStatic_ToLower) { mappedMethodName = "toLowerCase"; } else if (methodInfo == NonStatic_ToUpper) { mappedMethodName = "toUpperCase"; } else if (methodInfo == NonStatic_TrimStart) { mappedMethodName = "trimStart"; } else if (methodInfo == NonStatic_TrimEnd) { mappedMethodName = "trimEnd"; } else if (methodInfo == NonStatic_Trim) { mappedMethodName = "trim"; } else if (methodInfo == NonStatic_Substring_StartIndex) { mappedMethodName = "substring"; var startIndexExpression = methodCallExpression.Arguments[0]; var startIndex = _expressionProcessorPipeline.ProcessExpression(startIndexExpression, parameters); argumentList.Add(startIndex); } else if (methodInfo == NonStatic_Substring_StartIndex_Length) { mappedMethodName = "substring"; var startIndexExpression = methodCallExpression.Arguments[0]; var lengthExpression = methodCallExpression.Arguments[1]; var startIndex = _expressionProcessorPipeline.ProcessExpression(startIndexExpression, parameters); var length = _expressionProcessorPipeline.ProcessExpression(lengthExpression, parameters); argumentList.Add(startIndex); argumentList.Add(length); } else { result = default; return(false); } var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Object, parameters); var arguments = string.Join(", ", argumentList); result = $"{ownerExpressionString}.{mappedMethodName}({arguments})"; return(true); }
private bool TryProcessPredicatedAny(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { var invokedMethod = methodCallExpression.Method; if (invokedMethod.IsGenericMethod) { invokedMethod = invokedMethod.GetGenericMethodDefinition(); } if (invokedMethod == AnyExtensionWithPredicate) { // Since extensins are static, we must pass the first method invocation argument as the expression, // not the methodCallExpression.Object (because that is null). var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Arguments[0], parameters); var predicate = (LambdaExpression)methodCallExpression.Arguments[1]; var jsPredicateFunction = _expressionProcessorPipeline.ProcessExpression(predicate, parameters); if (IsInvokedOnDictionary(methodCallExpression)) { // Ugly but simple. Could write a loop instead so we could terminate early if a match is found. result = $"Object.keys({ownerExpressionString}).map(function(key) {{ return {{ Key: key, Value: {ownerExpressionString}[key] }}; }}).some({jsPredicateFunction})"; return(true); } result = $"({ownerExpressionString}).some({jsPredicateFunction})"; return(true); } result = default; return(false); }
private bool TryProcessPredicatelessAny(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { var invokedMethod = methodCallExpression.Method; if (invokedMethod.IsGenericMethod) { invokedMethod = invokedMethod.GetGenericMethodDefinition(); } if (invokedMethod == AnyExtensionWithoutPredicate) { // Since extensins are static, we must pass the first method invocation argument as the expression, // not the methodCallExpression.Object (because that is null). var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Arguments[0], parameters); if (IsInvokedOnDictionary(methodCallExpression)) { result = $"Object.keys({ownerExpressionString}).length > 0"; return(true); } result = $"{ownerExpressionString}.length > 0"; return(true); } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var binaryExpression = expression as BinaryExpression; if (binaryExpression == null) { result = default; return(false); } var operation = binaryExpression.NodeType; var left = _expressionProcessorPipeline.ProcessExpression(binaryExpression.Left, parameters); var right = _expressionProcessorPipeline.ProcessExpression(binaryExpression.Right, parameters); switch (operation) { case ExpressionType.Add: case ExpressionType.AddChecked: result = $"({left} + {right})"; return(true); case ExpressionType.And: result = $"({left} & {right})"; return(true); case ExpressionType.AndAlso: result = $"({left} && {right})"; return(true); case ExpressionType.ArrayIndex: result = $"{left}[{right}]"; return(true); case ExpressionType.Coalesce: result = $"({left} != null ? {left} : {right})"; return(true); case ExpressionType.Divide: result = $"({left} / {right})"; return(true); case ExpressionType.Equal: result = $"({left} == {right})"; return(true); case ExpressionType.ExclusiveOr: result = $"({left} ^ {right})"; return(true); case ExpressionType.GreaterThan: result = $"({left} > {right})"; return(true); case ExpressionType.GreaterThanOrEqual: result = $"({left} >= {right})"; return(true); case ExpressionType.LessThan: result = $"({left} < {right})"; return(true); case ExpressionType.LessThanOrEqual: result = $"({left} <= {right})"; return(true); case ExpressionType.Modulo: result = $"({left} % {right})"; return(true); case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: result = $"({left} * {right})"; return(true); case ExpressionType.NotEqual: result = $"({left} != {right})"; return(true); case ExpressionType.Or: result = $"({left} | {right})"; return(true); case ExpressionType.OrElse: result = $"({left} || {right})"; return(true); case ExpressionType.Subtract: case ExpressionType.SubtractChecked: result = $"({left} - {right})"; return(true); case ExpressionType.Assign: result = $"({left} = {right})"; return(true); case ExpressionType.Index: result = $"{left}[{right}]"; return(true); case ExpressionType.AddAssign: case ExpressionType.AddAssignChecked: result = $"({left} += {right})"; return(true); case ExpressionType.AndAssign: result = $"({left} &= {right})"; return(true); case ExpressionType.DivideAssign: result = $"({left} /= {right})"; return(true); case ExpressionType.ExclusiveOrAssign: result = $"({left} ^= {right})"; return(true); case ExpressionType.ModuloAssign: result = $"({left} %= {right})"; return(true); case ExpressionType.MultiplyAssign: case ExpressionType.MultiplyAssignChecked: result = $"({left} *= {right})"; return(true); case ExpressionType.OrAssign: result = $"({left} |= {right})"; return(true); case ExpressionType.SubtractAssign: case ExpressionType.SubtractAssignChecked: result = $"({left} -= {right})"; return(true); default: result = default; return(false); } }
private bool TryProcessStaticStringMethodInvocation(MethodCallExpression methodCallExpression, MethodInfo methodInfo, ScriptParameterDictionary parameters, out string result) { if (methodInfo == Static_IsNullOrEmpty) { var methodParameterExpression = methodCallExpression.Arguments[0]; var methodParameter = _expressionProcessorPipeline.ProcessExpression(methodParameterExpression, parameters); result = $"({methodParameter} == null || {methodParameter} == '')"; return(true); } else if (methodInfo == Static_IsNullOrWhiteSpace) { var methodParameterExpression = methodCallExpression.Arguments[0]; var methodParameter = _expressionProcessorPipeline.ProcessExpression(methodParameterExpression, parameters); result = $"({methodParameter} == null || {methodParameter}.trim() == '')"; return(true); } /* * else if (methodInfo == Static_Concat) * { * } * else if (methodInfo == Static_Join) * { * } */ result = null; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var unaryExpression = expression as UnaryExpression; if (unaryExpression == null) { result = default; return(false); } var operation = unaryExpression.NodeType; var operand = _expressionProcessorPipeline.ProcessExpression(unaryExpression.Operand, parameters); switch (operation) { case ExpressionType.ArrayLength: result = $"{operand}.length"; return(true); case ExpressionType.Convert: result = operand; return(true); case ExpressionType.Negate: result = $"-({operand})"; return(true); case ExpressionType.UnaryPlus: result = $"+({operand})"; return(true); case ExpressionType.Not: result = $"!({operand})"; return(true); case ExpressionType.Decrement: result = $"({operand} - 1)"; return(true); case ExpressionType.Increment: result = $"({operand} + 1)"; return(true); case ExpressionType.PreIncrementAssign: result = $"(++{operand})"; return(true); case ExpressionType.PreDecrementAssign: result = $"(--{operand})"; return(true); case ExpressionType.PostIncrementAssign: result = $"({operand}++)"; return(true); case ExpressionType.PostDecrementAssign: result = $"({operand}--)"; return(true); default: result = default; return(false); } }