コード例 #1
0
        /// <summary>
        /// Generates a method.
        /// </summary>
        /// <param name="methodDescription">
        /// The method description.
        /// </param>
        /// <returns>
        /// The generated method.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// The return type of the provided method is not supported.
        /// </exception>
        private static MethodDeclarationSyntax GenerateMethod(ActorMethodDescription methodDescription)
        {
            // Types
            var method = methodDescription.MethodInfo;

            Type asyncReturnType;

            if (!method.ReturnType.IsGenericType && (method.ReturnType == typeof(Task)))
            {
                asyncReturnType = typeof(void);
            }
            else if (method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>))
            {
                asyncReturnType = method.ReturnType.GenericTypeArguments[0];
            }
            else
            {
                throw new ArgumentException("Method return type is not Task or Task<T>.");
            }

            // Body statements
            var parameterReferences =
                method.GetParameters()
                .Select(
                    p => SF.Argument(SF.CastExpression(typeof(object).GetTypeSyntax(), SF.IdentifierName(p.Name))))
                .ToArray();
            var writeEventMethod = SF.ThisExpression().Member((EventProducerBase <object> _) => _.WriteEvent(default(string), default(object), default(object)));
            var writeEvent       =
                SF.ExpressionStatement(
                    SF.AwaitExpression(
                        SF.InvocationExpression(writeEventMethod)
                        .AddArgumentListArguments(SF.Argument(methodDescription.Name.GetLiteralExpression()))
                        .AddArgumentListArguments(parameterReferences)));

            var returnValue = asyncReturnType == typeof(void) ? null : SF.DefaultExpression(asyncReturnType.GetTypeSyntax());

            // Build and return the method.
            return
                (SF.MethodDeclaration(method.ReturnType.GetTypeSyntax(), methodDescription.MethodInfo.Name)
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.AsyncKeyword))
                 .AddParameterListParameters(method.GetParameterListSyntax())
                 .AddBodyStatements(writeEvent, SF.ReturnStatement(returnValue)));
        }
コード例 #2
0
        public ExpressionSyntax GetRoslynExpression(RoslynExpressionContext context)
        {
            var manager     = context.GetService(typeof(IGuildOptionsManager));
            var optionsType = context.ExpectedType.GetGenericArguments()[0];
            var typeSyntax  = S.ParseTypeName(optionsType.FullName.Replace('+', '.'));
            var getName     = S.GenericName(nameof(SettingExtensions.GetOptionsAsync)).WithTypeArgumentList(S.TypeArgumentList().AddArguments(typeSyntax));
            var get         = S.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, manager, getName);
            var guildId     = S.BinaryExpression(
                SyntaxKind.CoalesceExpression,
                context.GetRequestProperty(nameof(MessageRequest.GuildId)),
                S.ThrowExpression(S.ObjectCreationExpression(
                                      S.IdentifierName("InvalidOperationException"),
                                      S.ArgumentList().AddArguments(S.Argument(S.LiteralExpression(SyntaxKind.StringLiteralExpression, S.Literal(GuildIdNotDefined)))),
                                      null
                                      ))
                );
            var invoke = S.InvocationExpression(get, S.ArgumentList().AddArguments(S.Argument(guildId)));

            return(S.AwaitExpression(invoke));
        }
コード例 #3
0
        /// <summary>
        ///     Create a new <see cref="ExpressionSyntax"/> that invokes the <see cref="method"/>.
        /// </summary>
        /// <param name="moduleType">The module type.</param>
        /// <param name="method">The method to invoke.</param>
        /// <returns>The <see cref="ExpressionSyntax"/>.</returns>
        private ExpressionSyntax InvokeCommand(Type moduleType, MethodInfo method)
        {
            var moduleSyntaxType = S.ParseTypeName(moduleType.FullName.Replace('+', '.'));
            var listSyntax       = S.ArgumentList();

            var constructor = moduleType.GetConstructors().FirstOrDefault();

            if (constructor != null)
            {
                listSyntax = listSyntax.AddArguments(constructor.GetParameters().Select(p => S.Argument(GetValueFactory(p))).ToArray());
            }

            var moduleInstance  = S.ObjectCreationExpression(moduleSyntaxType).WithArgumentList(listSyntax);
            var contextProperty = moduleType
                                  .GetProperties()
                                  .FirstOrDefault(p => p.GetCustomAttributes <ModuleContextAttribute>().Any());

            if (contextProperty != null)
            {
                var contextInstance = S.ObjectCreationExpression(ModuleContextType)
                                      .WithInitializer(
                    S.InitializerExpression(
                        SyntaxKind.ObjectInitializerExpression,
                        S.SingletonSeparatedList <ExpressionSyntax>(
                            S.AssignmentExpression(
                                SyntaxKind.SimpleAssignmentExpression,
                                S.IdentifierName(nameof(ModuleContext.Context)),
                                S.IdentifierName(ArgumentContext)
                                ))));

                moduleInstance = moduleInstance.WithInitializer(
                    S.InitializerExpression(
                        SyntaxKind.ObjectInitializerExpression,
                        S.SingletonSeparatedList <ExpressionSyntax>(
                            S.AssignmentExpression(
                                SyntaxKind.SimpleAssignmentExpression,
                                S.IdentifierName(contextProperty.Name),
                                contextInstance
                                ))));
            }

            ExpressionSyntax invoke = S.InvocationExpression(
                S.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    moduleInstance,
                    S.IdentifierName(method.Name)
                    ),
                S.ArgumentList().AddArguments(method.GetParameters().Select(p => S.Argument(GetValueFactory(p))).ToArray())
                );

            if (method.ReturnType == typeof(Task) || method.ReturnType == typeof(ValueTask))
            {
                invoke = S.AwaitExpression(invoke);
            }
            else if (method.ReturnType != typeof(void))
            {
                throw new InvalidOperationException($"The return type {method.ReturnType.Name} is not supported.");
            }

            return(invoke);
        }
コード例 #4
0
        /// <summary>
        /// Generates syntax to invoke a method on a grain.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="grain">
        /// The grain instance expression.
        /// </param>
        /// <param name="method">
        /// The method.
        /// </param>
        /// <param name="arguments">
        /// The arguments expression.
        /// </param>
        /// <returns>
        /// Syntax to invoke a method on a grain.
        /// </returns>
        private static StatementSyntax[] GenerateInvokeForMethod(
            Type grainType,
            IdentifierNameSyntax grain,
            MethodInfo method,
            ExpressionSyntax arguments)
        {
            var castGrain = SF.ParenthesizedExpression(SF.CastExpression(grainType.GetTypeSyntax(), grain));

            // Construct expressions to retrieve each of the method's parameters.
            var parameters       = new List <ExpressionSyntax>();
            var methodParameters = method.GetParameters().ToList();

            for (var i = 0; i < methodParameters.Count; i++)
            {
                var parameter     = methodParameters[i];
                var parameterType = parameter.ParameterType.GetTypeSyntax();
                var indexArg      = SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(i)));
                var arg           = SF.CastExpression(
                    parameterType,
                    SF.ElementAccessExpression(arguments).AddArgumentListArguments(indexArg));
                parameters.Add(arg);
            }

            // If the method is a generic method definition, use the generic method invoker field to invoke the method.
            if (method.IsGenericMethodDefinition)
            {
                var invokerFieldName = GetGenericMethodInvokerFieldName(method);
                var invokerCall      = SF.InvocationExpression(
                    SF.IdentifierName(invokerFieldName)
                    .Member((GenericMethodInvoker invoker) => invoker.Invoke(null, null)))
                                       .AddArgumentListArguments(SF.Argument(grain), SF.Argument(arguments));
                return(new StatementSyntax[] { SF.ReturnStatement(SF.AwaitExpression(invokerCall)) });
            }

            // Invoke the method.
            var grainMethodCall =
                SF.InvocationExpression(castGrain.Member(method.Name))
                .AddArgumentListArguments(parameters.Select(SF.Argument).ToArray());

            // For void methods, invoke the method and return null.
            if (method.ReturnType == typeof(void))
            {
                return(new StatementSyntax[]
                {
                    SF.ExpressionStatement(grainMethodCall),
                    SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression))
                });
            }

            // For methods which return non-generic Task, await the method and return null.
            if (method.ReturnType == typeof(Task))
            {
                return(new StatementSyntax[]
                {
                    SF.ExpressionStatement(SF.AwaitExpression(grainMethodCall)),
                    SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression))
                });
            }

            if (method.ReturnType.IsGenericType &&
                method.ReturnType.GetGenericTypeDefinition().FullName == "System.Threading.Tasks.ValueTask`1")
            {
                var convertToTaskResult = SF.IdentifierName("AsTask");

                // Converting ValueTask method result to Task since "Invoke" method should return Task.
                // Temporary solution. Need to change when Orleans will be using ValueTask instead of Task.
                grainMethodCall =
                    SF.InvocationExpression(
                        SF.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                  SF.ExpressionStatement(grainMethodCall).Expression, convertToTaskResult));
            }


            return(new StatementSyntax[]
            {
                SF.ReturnStatement(SF.AwaitExpression(grainMethodCall))
            });
        }
コード例 #5
0
        /// <summary>
        /// Generates syntax to invoke a method on a grain.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="grain">
        /// The grain instance expression.
        /// </param>
        /// <param name="method">
        /// The method.
        /// </param>
        /// <param name="arguments">
        /// The arguments expression.
        /// </param>
        /// <returns>
        /// Syntax to invoke a method on a grain.
        /// </returns>
        private static StatementSyntax[] GenerateInvokeForMethod(
            Type grainType,
            IdentifierNameSyntax grain,
            MethodInfo method,
            ExpressionSyntax arguments)
        {
            var castGrain = SF.ParenthesizedExpression(SF.CastExpression(grainType.GetTypeSyntax(), grain));

            // Construct expressions to retrieve each of the method's parameters.
            var parameters       = new List <ExpressionSyntax>();
            var methodParameters = method.GetParameters().ToList();

            for (var i = 0; i < methodParameters.Count; i++)
            {
                var parameter     = methodParameters[i];
                var parameterType = parameter.ParameterType.GetTypeSyntax();
                var indexArg      = SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(i)));
                var arg           = SF.CastExpression(
                    parameterType,
                    SF.ElementAccessExpression(arguments).AddArgumentListArguments(indexArg));
                parameters.Add(arg);
            }

            // If the method is a generic method definition, use the generic method invoker field to invoke the method.
            if (method.IsGenericMethodDefinition)
            {
                var invokerFieldName = GetGenericMethodInvokerFieldName(method);
                var invokerCall      = SF.InvocationExpression(
                    SF.IdentifierName(invokerFieldName)
                    .Member((GenericMethodInvoker invoker) => invoker.Invoke(null, null)))
                                       .AddArgumentListArguments(SF.Argument(grain), SF.Argument(arguments));
                return(new StatementSyntax[] { SF.ReturnStatement(SF.AwaitExpression(invokerCall)) });
            }

            // Invoke the method.
            var grainMethodCall =
                SF.InvocationExpression(castGrain.Member(method.Name))
                .AddArgumentListArguments(parameters.Select(SF.Argument).ToArray());

            // For void methods, invoke the method and return null.
            if (method.ReturnType == typeof(void))
            {
                return(new StatementSyntax[]
                {
                    SF.ExpressionStatement(grainMethodCall),
                    SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression))
                });
            }

            // For methods which return non-generic Task, await the method and return null.
            if (method.ReturnType == typeof(Task))
            {
                return(new StatementSyntax[]
                {
                    SF.ExpressionStatement(SF.AwaitExpression(grainMethodCall)),
                    SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression))
                });
            }

            return(new StatementSyntax[]
            {
                SF.ReturnStatement(SF.AwaitExpression(grainMethodCall))
            });
        }