/// <summary>
        /// The generate dispatch block for method.
        /// </summary>
        /// <param name="methodDescription">
        /// The method description.
        /// </param>
        /// <param name="instance">
        /// The instance.
        /// </param>
        /// <param name="event">
        /// The event.
        /// </param>
        /// <returns>
        /// The <see cref="StatementSyntax"/>.
        /// </returns>
        private static StatementSyntax GenerateDispatchBlockForMethod(ActorMethodDescription methodDescription, IdentifierNameSyntax instance, IdentifierNameSyntax @event)
        {
            // Construct expressions to retrieve each of the method's parameters.
            var method           = methodDescription.MethodInfo;
            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 getArg =
                    SF.InvocationExpression(@event.Member("Arg", parameterType)).AddArgumentListArguments(indexArg);
                parameters.Add(getArg);
            }

            var grainMethodCall =
                SF.InvocationExpression(instance.Member(method.Name))
                .AddArgumentListArguments(parameters.Select(SF.Argument).ToArray());

            return(SF.ReturnStatement(SF.InvocationExpression(grainMethodCall.Member("Box"))));
        }
示例#2
0
        /// <summary>
        /// Returns the types referenced by the provided <paramref name="method"/>.
        /// </summary>
        /// <param name="method">
        /// The method.
        /// </param>
        /// <returns>
        /// The types referenced by the provided <paramref name="method"/>.
        /// </returns>
        public static IEnumerable <Type> GetTypes(ActorMethodDescription method)
        {
            foreach (var type in GetTypes(method.MethodInfo.ReturnType))
            {
                yield return(type);
            }

            foreach (
                var parameterType in
                method.MethodInfo.GetParameters().SelectMany(parameter => GetTypes(parameter.ParameterType)))
            {
                yield return(parameterType);
            }
        }
        /// <summary>
        /// Returns syntax for individual switch cases within the <see cref="IEventInvoker{T}.GetArgumentTypes"/> method.
        /// </summary>
        /// <param name="methodDescription">
        /// The method description.
        /// </param>
        /// <returns>
        /// Syntax for individual switch cases within the <see cref="IEventInvoker{T}.GetArgumentTypes"/> method.
        /// </returns>
        private static StatementSyntax GenerateGetTypeArgumentsSwitchBlock(ActorMethodDescription methodDescription)
        {
            var method     = methodDescription.MethodInfo;
            var parameters = method.GetParameters().ToList();

            var argumentTypes =
                parameters.Select(p => SF.TypeOfExpression(p.ParameterType.GetTypeSyntax()))
                .Cast <ExpressionSyntax>()
                .ToArray();

            var argumentTypeArray = SF.ArrayCreationExpression(typeof(Type).GetArrayTypeSyntax())
                                    .WithInitializer(
                SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression).AddExpressions(argumentTypes));

            return(SF.ReturnStatement(argumentTypeArray));
        }
        /// <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)));
        }
示例#5
0
        /// <summary>
        /// Returns syntax for dispatching <paramref name="event"/> to <paramref name="method"/>.
        /// </summary>
        /// <param name="event">
        /// The event.
        /// </param>
        /// <param name="method">
        /// The actor description.
        /// </param>
        /// <returns>
        /// Syntax for dispatching <paramref name="event"/> to <paramref name="method"/>.
        /// </returns>
        private static SwitchSectionSyntax GetMethodSwitchCase(ExpressionSyntax @event, ActorMethodDescription method)
        {
            var label =
                SF.CaseSwitchLabel(SF.LiteralExpression(SyntaxKind.StringLiteralExpression, SF.Literal(method.Name)));

            return
                (SF.SwitchSection()
                 .AddLabels(label)
                 .AddStatements(
                     GenerateMethodDispatcher(@event, SF.IdentifierName("grain"), method.MethodInfo)));
        }