public IDataFlowGraphOutput AddAssignment(VariableName name, IDataFlowGraphExpressionNode value) { var node = new AssignmentOutput(name, value, Guid.NewGuid()); _outputs.Add(node); return(node); }
private AssignmentOutput Build(Expression expression) { if (expression is MemberExpression memberExpression) { var owner = memberExpression.Expression; AssignmentOutput ownerAssignment = null; if (owner == null) { var memberDeclaringType = memberExpression.Member.DeclaringType; var name = memberDeclaringType.Name; ownerAssignment = new AssignmentOutput(name, name, memberDeclaringType, name); } else { ownerAssignment = Build(memberExpression.Expression); } if (memberExpression.Member is PropertyInfo propertyInfo) { var name = propertyInfo.Name; var fullName = $"{ownerAssignment.FullName}{propertyInfo.Name}"; return(new AssignmentOutput(name, fullName, propertyInfo.PropertyType, $"{ownerAssignment.Assignment}.{propertyInfo.Name}")); } if (memberExpression.Member is FieldInfo fieldInfo) { var name = fieldInfo.Name; var fullName = $"{ownerAssignment.FullName}{fieldInfo.Name}"; return(new AssignmentOutput(name, fullName, fieldInfo.FieldType, $"{ownerAssignment.Assignment}.{fieldInfo.Name}")); } } if (expression is ParameterExpression parameterExpression) { return(new AssignmentOutput("this", "", parameterExpression.Type, "$this")); } if (expression is ConstantExpression constantExpression) { if (constantExpression.Value is string stringValue) { return(new AssignmentOutput("const", "", constantExpression.Type, $"\"{stringValue}\"")); } if (constantExpression.Value == null) { return(new AssignmentOutput("const", "", constantExpression.Type, $"null")); } return(new AssignmentOutput("const", "", constantExpression.Type, $"\"{constantExpression.Value.ToString()}\"")); } if (expression is MethodCallExpression methodCallExpression) { AssignmentOutput callerAssignment = null; var arguments = GetCsvList(methodCallExpression.Arguments.Select(a => Build(a).Assignment)); // Non-static call if (methodCallExpression.Object != null) { callerAssignment = Build(methodCallExpression.Object); } // Extension method call else if (methodCallExpression.Method.IsDefined( typeof(System.Runtime.CompilerServices.ExtensionAttribute))) { var argumentsList = new List <Expression>(methodCallExpression.Arguments); var owner = argumentsList[0]; argumentsList.RemoveAt(0); arguments = GetCsvList(argumentsList.Select(a => Build(a).Assignment)); callerAssignment = Build(owner); } // Static method call else { var methodDeclaringType = methodCallExpression.Method.DeclaringType; var name = methodDeclaringType?.Name ?? ""; callerAssignment = new AssignmentOutput(name, name, methodDeclaringType, name); } var methodName = methodCallExpression.Method.Name; var assignment = $"{callerAssignment.Assignment}.{methodCallExpression.Method.Name}({arguments})"; var fullName = $"{callerAssignment.FullName}{methodCallExpression.Method.Name}"; if (methodCallExpression.Method.IsSpecialName && methodName == "get_Item") { assignment = $"{callerAssignment.Assignment}[{arguments}]"; fullName = $"{callerAssignment.FullName}{arguments}"; } return(new AssignmentOutput(methodName, fullName, methodCallExpression.Method.ReturnType, assignment)); } if (expression is BinaryExpression binaryExpression) { var left = Build(binaryExpression.Left); var type = left.Type; var op = ""; var name = ""; var fullName = ""; var right = Build(binaryExpression.Right); switch (binaryExpression.NodeType) { case (ExpressionType.Coalesce): op = "??"; name = left.Name; fullName = left.FullName; type = Nullable.GetUnderlyingType(type) ?? type; break; case (ExpressionType.Equal): op = "=="; name = left.Name; fullName = ""; break; case (ExpressionType.NotEqual): op = "!="; name = left.Name; fullName = ""; break; default: throw new NotSupportedException($"Binary Expression of type {binaryExpression.NodeType} is not supported yet"); } return(new AssignmentOutput(name, fullName, type, $"{left.Assignment} {op} {right.Assignment}")); } if (expression is ConditionalExpression conditionalExpression) { var test = Build(conditionalExpression.Test); var ifTrue = Build(conditionalExpression.IfTrue); var ifFalse = Build(conditionalExpression.IfFalse); var name = ifTrue.Name; var fullName = string.IsNullOrWhiteSpace(ifTrue.FullName) ? ifFalse.FullName : ifTrue.FullName; return(new AssignmentOutput(name, fullName, ifTrue.Type, $"{test.Assignment} ? {ifTrue.Assignment} : {ifFalse.Assignment}")); } throw new NotSupportedException($"Expression of type {expression.NodeType} is not supported yet"); }