/// <summary> /// Generates syntax for an invoke method. /// </summary> /// <param name="grainType"> /// The grain type. /// </param> /// <param name="invokeMethod"> /// The invoke method to generate. /// </param> /// <returns> /// Syntax for an invoke method. /// </returns> private static MethodDeclarationSyntax GenerateInvokeMethod(Type grainType, MethodInfo invokeMethod) { var methodDeclaration = invokeMethod.GetDeclarationSyntax(); var parameters = invokeMethod.GetParameters(); var grainArgument = parameters[0].Name.ToIdentifierName(); var interfaceIdArgument = parameters[1].Name.ToIdentifierName(); var methodIdArgument = parameters[2].Name.ToIdentifierName(); var argumentsArgument = parameters[3].Name.ToIdentifierName(); var interfaceCases = CodeGeneratorCommon.GenerateGrainInterfaceAndMethodSwitch( grainType, methodIdArgument, methodType => GenerateInvokeForMethod(grainType, grainArgument, methodType, argumentsArgument)); // Generate the default case, which will throw a NotImplementedException. var errorMessage = SF.BinaryExpression( SyntaxKind.AddExpression, "interfaceId=".GetLiteralExpression(), interfaceIdArgument); var throwStatement = SF.ThrowStatement( SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax()) .AddArgumentListArguments(SF.Argument(errorMessage))); var defaultCase = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement); var interfaceIdSwitch = SF.SwitchStatement(interfaceIdArgument).AddSections(interfaceCases.ToArray()).AddSections(defaultCase); // If the provided grain is null, throw an argument exception. var argumentNullException = SF.ObjectCreationExpression(typeof(ArgumentNullException).GetTypeSyntax()) .AddArgumentListArguments(SF.Argument(parameters[0].Name.GetLiteralExpression())); var grainArgumentCheck = SF.IfStatement( SF.BinaryExpression( SyntaxKind.EqualsExpression, grainArgument, SF.LiteralExpression(SyntaxKind.NullLiteralExpression)), SF.ThrowStatement(argumentNullException)); // Wrap everything in a try-catch block. var faulted = (Expression <Func <Task <object> > >)(() => TaskUtility.Faulted(null)); const string Exception = "exception"; var exception = SF.Identifier(Exception); var body = SF.TryStatement() .AddBlockStatements(grainArgumentCheck, interfaceIdSwitch) .AddCatches( SF.CatchClause() .WithDeclaration( SF.CatchDeclaration(typeof(Exception).GetTypeSyntax()).WithIdentifier(exception)) .AddBlockStatements( SF.ReturnStatement( faulted.Invoke().AddArgumentListArguments(SF.Argument(SF.IdentifierName(Exception)))))); return(methodDeclaration.AddBodyStatements(body)); }