Example #1
0
        /// <summary>
        /// Generates switch cases for the provided grain type.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="methodIdArgument">
        /// The method id argument, which is used to select the correct switch label.
        /// </param>
        /// <param name="generateMethodHandler">
        /// The function used to generate switch block statements for each method.
        /// </param>
        /// <returns>
        /// The switch cases for the provided grain type.
        /// </returns>
        public static SwitchSectionSyntax[] GenerateGrainInterfaceAndMethodSwitch(
            Type grainType,
            IdentifierNameSyntax methodIdArgument,
            Func <MethodInfo, StatementSyntax[]> generateMethodHandler)
        {
            var interfaces = GrainInterfaceData.GetRemoteInterfaces(grainType);

            interfaces[GrainInterfaceData.GetGrainInterfaceId(grainType)] = grainType;

            // Switch on interface id.
            var interfaceCases = new List <SwitchSectionSyntax>();

            foreach (var @interface in interfaces)
            {
                var interfaceType = @interface.Value;
                var interfaceId   = @interface.Key;
                var methods       = GrainInterfaceData.GetMethods(interfaceType);

                var methodCases = new List <SwitchSectionSyntax>();

                // Switch on method id.
                foreach (var method in methods)
                {
                    // Generate switch case.
                    var methodId   = GrainInterfaceData.ComputeMethodId(method);
                    var methodType = method;

                    // Generate the switch label for this interface id.
                    var methodIdSwitchLabel =
                        SF.CaseSwitchLabel(
                            SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId)));

                    // Generate the switch body.
                    var methodInvokeStatement = generateMethodHandler(methodType);

                    methodCases.Add(
                        SF.SwitchSection().AddLabels(methodIdSwitchLabel).AddStatements(methodInvokeStatement));
                }

                // Generate the switch label for this interface id.
                var interfaceIdSwitchLabel =
                    SF.CaseSwitchLabel(
                        SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)));

                // Generate the default case, which will throw a NotImplementedException.
                var errorMessage = SF.BinaryExpression(
                    SyntaxKind.AddExpression,
                    "interfaceId=".GetLiteralExpression(),
                    SF.BinaryExpression(
                        SyntaxKind.AddExpression,
                        SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)),
                        SF.BinaryExpression(
                            SyntaxKind.AddExpression,
                            ",methodId=".GetLiteralExpression(),
                            methodIdArgument)));
                var throwStatement =
                    SF.ThrowStatement(
                        SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax())
                        .AddArgumentListArguments(SF.Argument(errorMessage)));
                var defaultCase = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement);

                // Generate switch statements for the methods in this interface.
                var methodSwitchStatements =
                    SF.SwitchStatement(methodIdArgument).AddSections(methodCases.ToArray()).AddSections(defaultCase);

                // Generate the switch section for this interface.
                interfaceCases.Add(
                    SF.SwitchSection().AddLabels(interfaceIdSwitchLabel).AddStatements(methodSwitchStatements));
            }

            return(interfaceCases.ToArray());
        }
Example #2
0
        /// <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       = GrainInterfaceData.GetMethods(grainType);
            var members       = new List <MemberDeclarationSyntax>();

            foreach (var method in methods)
            {
                onEncounteredType(method.ReturnType);
                var methodId         = GrainInterfaceData.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
                {
                    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());
        }
Example #3
0
        protected override string GetBasicMethodImpl(MethodInfo methodInfo)
        {
            string invokeArguments = GetInvokeArguments(methodInfo);
            int    methodId        = GrainInterfaceData.ComputeMethodId(methodInfo);
            string methodImpl;
            string optional = null;

            if (GrainInterfaceData.IsReadOnly(methodInfo))
            {
                optional = ", options: global::Orleans.CodeGeneration.InvokeMethodOptions.ReadOnly";
            }

            if (GrainInterfaceData.IsUnordered(methodInfo))
            {
                if (optional == null)
                {
                    optional = ", options: ";
                }
                else
                {
                    optional += " | ";
                }

                optional += " global::Orleans.CodeGeneration.InvokeMethodOptions.Unordered";
            }

            if (GrainInterfaceData.IsAlwaysInterleave(methodInfo))
            {
                if (optional == null)
                {
                    optional = ", options: ";
                }
                else
                {
                    optional += " | ";
                }

                optional += " global::Orleans.CodeGeneration.InvokeMethodOptions.AlwaysInterleave";
            }

            if (methodInfo.ReturnType == typeof(void))
            {
                methodImpl = string.Format(@"
                    base.InvokeOneWayMethod({0}, {1} {2});",
                                           methodId,
                                           invokeArguments.Equals(string.Empty) ? "null" : String.Format("new object[] {{{0}}}", invokeArguments),
                                           optional);
            }
            else
            {
                if (methodInfo.ReturnType == typeof(Task))
                {
                    methodImpl = string.Format(@"
                return base.InvokeMethodAsync<object>({0}, {1} {2});",
                                               methodId,
                                               invokeArguments.Equals(string.Empty) ? "null" : String.Format("new object[] {{{0}}}", invokeArguments),
                                               optional);
                }
                else
                {
                    methodImpl = string.Format(@"
                return base.InvokeMethodAsync<{0}>({1}, {2} {3});",
                                               GetActualMethodReturnType(methodInfo.ReturnType, SerializeFlag.NoSerialize),
                                               methodId,
                                               invokeArguments.Equals(string.Empty) ? "null" : String.Format("new object[] {{{0}}}", invokeArguments),
                                               optional);
                }
            }
            return(GetParamGuardCheckStatements(methodInfo) + methodImpl);
        }
Example #4
0
        protected override string GetBasicMethodImpl(MethodInfo methodInfo)
        {
            var invokeArguments = GetInvokeArguments(methodInfo);

            int    methodId = GrainInterfaceData.ComputeMethodId(methodInfo);
            string methodImpl;
            string optional = null;

            if (GrainInterfaceData.IsReadOnly(methodInfo))
            {
                optional = ", options:= Global.Orleans.CodeGeneration.InvokeMethodOptions.ReadOnly";
            }

            if (GrainInterfaceData.IsUnordered(methodInfo))
            {
                if (optional == null)
                {
                    optional = ", options:= ";
                }
                else
                {
                    optional += " | ";
                }

                optional += " Global.Orleans.CodeGeneration.InvokeMethodOptions.Unordered";
            }

            if (GrainInterfaceData.IsAlwaysInterleave(methodInfo))
            {
                if (optional == null)
                {
                    optional = ", options:= ";
                }
                else
                {
                    optional += " | ";
                }

                optional += " Global.Orleans.CodeGeneration.InvokeMethodOptions.AlwaysInterleave";
            }

            if (methodInfo.ReturnType == typeof(void))
            {
                methodImpl = string.Format(@"
                MyBase.InvokeOneWayMethod({0}, New System.Object() {{{1}}} {2})",
                                           methodId, invokeArguments, optional);
            }
            else
            {
                if (methodInfo.ReturnType == typeof(Task))
                {
                    methodImpl = string.Format(@"
                Return MyBase.InvokeMethodAsync(Of System.Object)({0}, New System.Object() {{{1}}} {2})",
                                               methodId,
                                               invokeArguments,
                                               optional);
                }
                else
                {
                    methodImpl = string.Format(@"
                Return MyBase.InvokeMethodAsync(Of {0})({1}, New System.Object() {{{2}}} {3})",
                                               GetActualMethodReturnType(methodInfo.ReturnType, SerializeFlag.NoSerialize),
                                               methodId,
                                               invokeArguments,
                                               optional);
                }
            }
            return(GetParamGuardCheckStatements(methodInfo) + methodImpl);
        }