/// <summary> /// Generates invoker methods. /// </summary> /// <param name="grainType">The grain type.</param> /// <param name="onEncounteredType"> /// The callback which is invoked when a type is encountered. /// </param> /// <returns>Invoker methods for the provided grain type.</returns> private static MemberDeclarationSyntax[] GenerateInvokeMethods(Type grainType, Action <Type> onEncounteredType) { var baseReference = SF.BaseExpression(); var methods = GrainInterfaceUtils.GetMethods(grainType); var members = new List <MemberDeclarationSyntax>(); foreach (var method in methods) { onEncounteredType(method.ReturnType); var methodId = GrainInterfaceUtils.ComputeMethodId(method); var methodIdArgument = SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId))); // Construct a new object array from all method arguments. var parameters = method.GetParameters(); var body = new List <StatementSyntax>(); foreach (var parameter in parameters) { onEncounteredType(parameter.ParameterType); if (typeof(IGrainObserver).IsAssignableFrom(parameter.ParameterType)) { body.Add( SF.ExpressionStatement( CheckGrainObserverParamInternalExpression.Invoke() .AddArgumentListArguments(SF.Argument(parameter.Name.ToIdentifierName())))); } } // Get the parameters argument value. ExpressionSyntax args; if (parameters.Length == 0) { args = SF.LiteralExpression(SyntaxKind.NullLiteralExpression); } else { args = SF.ArrayCreationExpression(typeof(object).GetArrayTypeSyntax()) .WithInitializer( SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression) .AddExpressions(parameters.Select(GetParameterForInvocation).ToArray())); } var options = GetInvokeOptions(method); // Construct the invocation call. if (method.ReturnType == typeof(void)) { var invocation = SF.InvocationExpression(baseReference.Member("InvokeOneWayMethod")) .AddArgumentListArguments(methodIdArgument) .AddArgumentListArguments(SF.Argument(args)); if (options != null) { invocation = invocation.AddArgumentListArguments(options); } body.Add(SF.ExpressionStatement(invocation)); } //else if (GrainInterfaceUtils.IsReactiveComputationType(method.ReturnType)) //{ // var resultTypeArgument = // SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId))); // var returnType = method.ReturnType.GenericTypeArguments[0]; // args = // SF.ArrayCreationExpression(typeof(object).GetArrayTypeSyntax()) // .WithInitializer( // SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression) // .AddExpressions(parameters.Select(GetParameterForInvocation).ToArray())); // var invocation = // SF.InvocationExpression(baseReference.Member("CreateReactiveComputation", returnType.GenericTypeArguments[0])) // .AddArgumentListArguments(methodIdArgument) // .AddArgumentListArguments(SF.Argument(args)); // if (options != null) // { // invocation = invocation.AddArgumentListArguments(options); // } // body.Add(SF.ReturnStatement(invocation)); //} //else if (grainType is IReactiveGrain) //{ // var returnType = (method.ReturnType == typeof(Task)) // ? typeof(object) // : method.ReturnType.GenericTypeArguments[0]; // var invocation = // SF.InvocationExpression(baseReference.Member("InvokeMethodAsync", returnType)) // .AddArgumentListArguments(methodIdArgument) // .AddArgumentListArguments(SF.Argument(args)); // if (options != null) // { // invocation = invocation.AddArgumentListArguments(options); // } // body.Add(SF.ReturnStatement(invocation)); //} else if (GrainInterfaceUtils.IsTaskType(method.ReturnType)) { var returnType = (method.ReturnType == typeof(Task)) ? typeof(object) : method.ReturnType.GenericTypeArguments[0]; var invocation = SF.InvocationExpression(baseReference.Member("InvokeMethodAsync", returnType)) .AddArgumentListArguments(methodIdArgument) .AddArgumentListArguments(SF.Argument(args)); if (options != null) { invocation = invocation.AddArgumentListArguments(options); } body.Add(SF.ReturnStatement(invocation)); } members.Add(method.GetDeclarationSyntax().AddBodyStatements(body.ToArray())); } return(members.ToArray()); }