コード例 #1
0
        /// <summary>
        /// Returns syntax for initializing a new instance of the provided type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>Syntax for initializing a new instance of the provided type.</returns>
        private static ExpressionSyntax GetObjectCreationExpressionSyntax(Type type)
        {
            ExpressionSyntax result;
            var typeInfo = type.GetTypeInfo();

            if (typeInfo.IsValueType)
            {
                // Use the default value.
                result = SF.DefaultExpression(typeInfo.AsType().GetTypeSyntax());
            }
            else if (GetEmptyConstructor(typeInfo) != null)
            {
                // Use the default constructor.
                result = SF.ObjectCreationExpression(typeInfo.AsType().GetTypeSyntax()).AddArgumentListArguments();
            }
            else
            {
                // Create an unformatted object.
                Expression <Func <object> > getUninitializedObject =
                    () => FormatterServices.GetUninitializedObject(default(Type));

                result = SF.CastExpression(
                    type.GetTypeSyntax(),
                    getUninitializedObject.Invoke()
                    .AddArgumentListArguments(
                        SF.Argument(SF.TypeOfExpression(typeInfo.AsType().GetTypeSyntax()))));
            }

            return(result);
        }
コード例 #2
0
            public ExpressionSyntax GetGetter(ExpressionSyntax instance, bool forceAvoidCopy = false)
            {
                Expression <Action> fieldGetter = () => this.FieldInfo.GetValue(default(object));
                var getFieldExpression          =
                    fieldGetter.Invoke(this.FieldInfoExpression).AddArgumentListArguments(SF.Argument(instance));

                // If the field is the backing field for an auto-property, try to use the property directly.
                var propertyName = Regex.Match(this.FieldInfo.Name, "^<([^>]+)>.*$");

                if (propertyName.Success && this.FieldInfo.DeclaringType != null)
                {
                    var name     = propertyName.Groups[1].Value;
                    var property = this.FieldInfo.DeclaringType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
                    if (property != null && property.GetGetMethod() != null)
                    {
                        return(instance.Member(property.Name));
                    }
                }

                if (forceAvoidCopy || this.FieldInfo.FieldType.IsOrleansShallowCopyable())
                {
                    // Shallow-copy the field.
                    return(getFieldExpression);
                }

                // Deep-copy the field.
                Expression <Action> deepCopyInner = () => SerializationManager.DeepCopyInner(default(object));

                return(SF.CastExpression(
                           this.FieldInfo.FieldType.GetTypeSyntax(),
                           deepCopyInner.Invoke().AddArgumentListArguments(SF.Argument(getFieldExpression))));
            }
コード例 #3
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);
            }

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

            if (method.ReturnType == typeof(void))
            {
                var completed = (Expression <Func <Task <object> > >)(() => TaskUtility.Completed());
                return(new StatementSyntax[]
                {
                    SF.ExpressionStatement(grainMethodCall), SF.ReturnStatement(completed.Invoke())
                });
            }

            //// Generate a Task wrapper for a query method
            //if (GrainInterfaceUtils.IsQueryType(method.ReturnType))
            //{
            //    var TaskFromResult = SF.InvocationExpression(
            //        SF.MemberAccessExpression(
            //            SyntaxKind.SimpleMemberAccessExpression,
            //            SF.IdentifierName("global::System.Threading.Tasks.Task"),
            //            SF.IdentifierName("FromResult")),
            //        SF.ArgumentList(SF.SeparatedList(new[] { SF.Argument(grainMethodCall) })));
            //    return new StatementSyntax[]
            //{
            //    SF.ReturnStatement(SF.InvocationExpression(TaskFromResult.Member((Task _) => _.Box())))
            //};
            //}

            // The invoke method expects a Task<object>, so we need to upcast the returned value.
            // For methods which do not return a value, the Box extension method returns a meaningless value.
            return(new StatementSyntax[]
            {
                SF.ReturnStatement(SF.InvocationExpression(grainMethodCall.Member((Task _) => _.Box())))
            });
        }
コード例 #4
0
            /// <summary>
            /// Returns syntax for retrieving the value of this field, deep copying it if necessary.
            /// </summary>
            /// <param name="instance">The instance of the containing type.</param>
            /// <param name="serializationContextExpression">The expression used to retrieve the serialization context.</param>
            /// <param name="forceAvoidCopy">Whether or not to ensure that no copy of the field is made.</param>
            /// <returns>Syntax for retrieving the value of this field.</returns>
            public ExpressionSyntax GetGetter(ExpressionSyntax instance, ExpressionSyntax serializationContextExpression = null, bool forceAvoidCopy = false)
            {
                // Retrieve the value of the field.
                var getValueExpression = this.GetValueExpression(instance);

                // Avoid deep-copying the field if possible.
                if (forceAvoidCopy || this.FieldInfo.FieldType.IsOrleansShallowCopyable())
                {
                    // Return the value without deep-copying it.
                    return(getValueExpression);
                }

                // Addressable arguments must be converted to references before passing.
                // IGrainObserver instances cannot be directly converted to references, therefore they are not included.
                ExpressionSyntax deepCopyValueExpression;

                if (typeof(IAddressable).IsAssignableFrom(this.FieldInfo.FieldType) &&
                    this.FieldInfo.FieldType.GetTypeInfo().IsInterface &&
                    !typeof(IGrainObserver).IsAssignableFrom(this.FieldInfo.FieldType))
                {
                    var getAsReference = getValueExpression.Member(
                        (IAddressable grain) => grain.AsReference <IGrain>(),
                        this.FieldInfo.FieldType);

                    // If the value is not a GrainReference, convert it to a strongly-typed GrainReference.
                    // C#: (value == null || value is GrainReference) ? value : value.AsReference<TInterface>()
                    deepCopyValueExpression =
                        SF.ConditionalExpression(
                            SF.ParenthesizedExpression(
                                SF.BinaryExpression(
                                    SyntaxKind.LogicalOrExpression,
                                    SF.BinaryExpression(
                                        SyntaxKind.EqualsExpression,
                                        getValueExpression,
                                        SF.LiteralExpression(SyntaxKind.NullLiteralExpression)),
                                    SF.BinaryExpression(
                                        SyntaxKind.IsExpression,
                                        getValueExpression,
                                        typeof(GrainReference).GetTypeSyntax()))),
                            getValueExpression,
                            SF.InvocationExpression(getAsReference));
                }
                else
                {
                    deepCopyValueExpression = getValueExpression;
                }

                // Deep-copy the value.
                Expression <Action> deepCopyInner = () => SerializationManager.DeepCopyInner(default(object), default(ICopyContext));
                var typeSyntax = this.FieldInfo.FieldType.GetTypeSyntax();

                return(SF.CastExpression(
                           typeSyntax,
                           deepCopyInner.Invoke()
                           .AddArgumentListArguments(
                               SF.Argument(deepCopyValueExpression),
                               SF.Argument(serializationContextExpression))));
            }
コード例 #5
0
        /// <summary>
        /// Returns syntax for the deserializer method.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="fields">The fields.</param>
        /// <returns>Syntax for the deserializer method.</returns>
        private static MemberDeclarationSyntax GenerateDeserializerMethod(Type type, List <FieldInfoMember> fields)
        {
            Expression <Action> deserializeInner =
                () => SerializationManager.DeserializeInner(default(Type), default(IDeserializationContext));
            var contextParameter = SF.IdentifierName("context");

            var resultDeclaration =
                SF.LocalDeclarationStatement(
                    SF.VariableDeclaration(type.GetTypeSyntax())
                    .AddVariables(
                        SF.VariableDeclarator("result")
                        .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type)))));
            var resultVariable = SF.IdentifierName("result");

            var body = new List <StatementSyntax> {
                resultDeclaration
            };

            // Value types cannot be referenced, only copied, so there is no need to box & record instances of value types.
            if (!type.GetTypeInfo().IsValueType)
            {
                // Record the result for cyclic deserialization.
                Expression <Action <IDeserializationContext> > recordObject = ctx => ctx.RecordObject(default(object));
                var currentSerializationContext = contextParameter;
                body.Add(
                    SF.ExpressionStatement(
                        recordObject.Invoke(currentSerializationContext)
                        .AddArgumentListArguments(SF.Argument(resultVariable))));
            }

            // Deserialize all fields.
            foreach (var field in fields)
            {
                var deserialized =
                    deserializeInner.Invoke()
                    .AddArgumentListArguments(
                        SF.Argument(SF.TypeOfExpression(field.Type)),
                        SF.Argument(contextParameter));
                body.Add(
                    SF.ExpressionStatement(
                        field.GetSetter(
                            resultVariable,
                            SF.CastExpression(field.Type, deserialized))));
            }

            body.Add(SF.ReturnStatement(SF.CastExpression(type.GetTypeSyntax(), resultVariable)));
            return
                (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "Deserializer")
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword))
                 .AddParameterListParameters(
                     SF.Parameter(SF.Identifier("expected")).WithType(typeof(Type).GetTypeSyntax()),
                     SF.Parameter(SF.Identifier("context")).WithType(typeof(IDeserializationContext).GetTypeSyntax()))
                 .AddBodyStatements(body.ToArray())
                 .AddAttributeLists(
                     SF.AttributeList()
                     .AddAttributes(SF.Attribute(typeof(DeserializerMethodAttribute).GetNameSyntax()))));
        }
コード例 #6
0
        private static MemberDeclarationSyntax GenerateDeserializerMethod(Type type, List <FieldInfoMember> fields)
        {
            Expression <Action> deserializeInner =
                () => SerializationManager.DeserializeInner(default(Type), default(BinaryTokenStreamReader));
            var streamParameter = SF.IdentifierName("stream");

            var resultDeclaration =
                SF.LocalDeclarationStatement(
                    SF.VariableDeclaration(type.GetTypeSyntax())
                    .AddVariables(
                        SF.VariableDeclarator("result")
                        .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type)))));
            var resultVariable      = SF.IdentifierName("result");
            var boxedResultVariable = resultVariable;

            var body = new List <StatementSyntax> {
                resultDeclaration
            };

            if (type.IsValueType)
            {
                // For value types, we need to box the result for reflection-based setters to work.
                body.Add(SF.LocalDeclarationStatement(
                             SF.VariableDeclaration(typeof(object).GetTypeSyntax())
                             .AddVariables(
                                 SF.VariableDeclarator("boxedResult").WithInitializer(SF.EqualsValueClause(resultVariable)))));
                boxedResultVariable = SF.IdentifierName("boxedResult");
            }

            // Deserialize all fields.
            foreach (var field in fields)
            {
                var deserialized =
                    deserializeInner.Invoke()
                    .AddArgumentListArguments(
                        SF.Argument(SF.TypeOfExpression(field.Type)),
                        SF.Argument(streamParameter));
                body.Add(
                    SF.ExpressionStatement(
                        field.GetSetter(
                            resultVariable,
                            SF.CastExpression(field.Type, deserialized),
                            boxedResultVariable)));
            }

            body.Add(SF.ReturnStatement(SF.CastExpression(type.GetTypeSyntax(), boxedResultVariable)));
            return
                (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "Deserializer")
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword))
                 .AddParameterListParameters(
                     SF.Parameter(SF.Identifier("expected")).WithType(typeof(Type).GetTypeSyntax()),
                     SF.Parameter(SF.Identifier("stream")).WithType(typeof(BinaryTokenStreamReader).GetTypeSyntax()))
                 .AddBodyStatements(body.ToArray())
                 .AddAttributeLists(
                     SF.AttributeList()
                     .AddAttributes(SF.Attribute(typeof(DeserializerMethodAttribute).GetNameSyntax()))));
        }
コード例 #7
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);
            }

            // 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 a completed task.
            if (method.ReturnType == typeof(void))
            {
                var completed = (Expression <Func <Task <object> > >)(() => TaskUtility.Completed());
                return(new StatementSyntax[]
                {
                    SF.ExpressionStatement(grainMethodCall), SF.ReturnStatement(completed.Invoke())
                });
            }

            // For methods which return the expected type, Task<object>, simply return that.
            if (method.ReturnType == typeof(Task <object>))
            {
                return(new StatementSyntax[] { SF.ReturnStatement(grainMethodCall) });
            }

            // The invoke method expects a Task<object>, so we need to upcast the returned value.
            // For methods which do not return a value, the Box extension method returns a meaningless value.
            return(new StatementSyntax[]
            {
                SF.ReturnStatement(SF.InvocationExpression(grainMethodCall.Member((Task _) => _.Box())))
            });
        }
コード例 #8
0
        private static MemberDeclarationSyntax GenerateSerializerMethod(Type type, List <FieldInfoMember> fields)
        {
            Expression <Action> serializeInner =
                () =>
                SerializationManager.SerializeInner(default(object), default(ISerializationContext), default(Type));
            var contextParameter = SF.IdentifierName("context");

            var body = new List <StatementSyntax>
            {
                SF.LocalDeclarationStatement(
                    SF.VariableDeclaration(type.GetTypeSyntax())
                    .AddVariables(
                        SF.VariableDeclarator("input")
                        .WithInitializer(
                            SF.EqualsValueClause(
                                SF.CastExpression(type.GetTypeSyntax(), SF.IdentifierName("untypedInput"))))))
            };

            var inputExpression = SF.IdentifierName("input");

            // Serialize all members.
            foreach (var field in fields)
            {
                body.Add(
                    SF.ExpressionStatement(
                        serializeInner.Invoke()
                        .AddArgumentListArguments(
                            SF.Argument(field.GetGetter(inputExpression, forceAvoidCopy: true)),
                            SF.Argument(contextParameter),
                            SF.Argument(SF.TypeOfExpression(field.FieldInfo.FieldType.GetTypeSyntax())))));
            }

            return
                (SF.MethodDeclaration(typeof(void).GetTypeSyntax(), "Serializer")
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword))
                 .AddParameterListParameters(
                     SF.Parameter(SF.Identifier("untypedInput")).WithType(typeof(object).GetTypeSyntax()),
                     SF.Parameter(SF.Identifier("context")).WithType(typeof(ISerializationContext).GetTypeSyntax()),
                     SF.Parameter(SF.Identifier("expected")).WithType(typeof(Type).GetTypeSyntax()))
                 .AddBodyStatements(body.ToArray())
                 .AddAttributeLists(
                     SF.AttributeList()
                     .AddAttributes(SF.Attribute(typeof(SerializerMethodAttribute).GetNameSyntax()))));
        }
コード例 #9
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)));
        }
コード例 #10
0
            /// <summary>
            /// Returns syntax for retrieving the value of this field, deep copying it if neccessary.
            /// </summary>
            /// <param name="instance">The instance of the containing type.</param>
            /// <param name="forceAvoidCopy">Whether or not to ensure that no copy of the field is made.</param>
            /// <returns>Syntax for retrieving the value of this field.</returns>
            public ExpressionSyntax GetGetter(ExpressionSyntax instance, bool forceAvoidCopy = false)
            {
                // Retrieve the value of the field.
                var getValueExpression = this.GetValueExpression(instance);

                // Avoid deep-copying the field if possible.
                if (forceAvoidCopy || this.FieldInfo.FieldType.IsOrleansShallowCopyable())
                {
                    // Return the value without deep-copying it.
                    return getValueExpression;
                }

                // Deep-copy the value.
                Expression<Action> deepCopyInner = () => SerializationManager.DeepCopyInner(default(object));
                var typeSyntax = this.FieldInfo.FieldType.GetTypeSyntax();
                return SF.CastExpression(
                    typeSyntax,
                    deepCopyInner.Invoke().AddArgumentListArguments(SF.Argument(getValueExpression)));
            }
コード例 #11
0
        private MemberDeclarationSyntax MockProviderMethod()
        {
            var m = F.MethodDeclaration(MockMemberType, F.Identifier(MemberMockName)).WithTypeParameterList(TypeParameterList());

            m = m.WithModifiers(F.TokenList(F.Token(SyntaxKind.PublicKeyword)));

            var keyCreation = F.LocalDeclarationStatement(F.VariableDeclaration(F.IdentifierName("var")).WithVariables(F.SingletonSeparatedList(F
                                                                                                                                                .VariableDeclarator(F.Identifier("key")).WithInitializer(F.EqualsValueClause(TypesOfTypeParameters())))));

            var mockCreation = F.SimpleLambdaExpression(F.Parameter(F.Identifier("keyString")), F.ObjectCreationExpression(MockMemberType)
                                                        .WithExpressionsAsArgumentList(
                                                            F.ThisExpression(),
                                                            F.LiteralExpression(SyntaxKind.StringLiteralExpression, F.Literal(ClassSymbol.Name)),
                                                            F.LiteralExpression(SyntaxKind.StringLiteralExpression, F.Literal(InterfaceSymbol.Name)),
                                                            F.BinaryExpression(SyntaxKind.AddExpression, F.LiteralExpression(SyntaxKind.StringLiteralExpression, F.Literal(Symbol.Name)),
                                                                               F.IdentifierName("keyString")),
                                                            F.BinaryExpression(SyntaxKind.AddExpression,
                                                                               F.BinaryExpression(SyntaxKind.AddExpression,
                                                                                                  F.LiteralExpression(SyntaxKind.StringLiteralExpression, F.Literal(MemberMockName)), F.IdentifierName("keyString")),
                                                                               F.LiteralExpression(
                                                                                   SyntaxKind.StringLiteralExpression,
                                                                                   F.Literal("()"))),
                                                            StrictnessExpression()
                                                            ));

            var returnStatement = F.ReturnStatement(F.CastExpression(MockMemberType, F.InvocationExpression(
                                                                         F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(MockProviderName),
                                                                                                  F.IdentifierName("GetOrAdd")))
                                                                     .WithArgumentList(
                                                                         F.ArgumentList(F.SeparatedList(new[] { F.Argument(F.IdentifierName("key")), F.Argument(mockCreation) })))));

            m = m.WithBody(F.Block(keyCreation, returnStatement));

            var constraints = TypesForSymbols.AsConstraintClauses(Symbol.TypeParameters);

            if (constraints.Any())
            {
                m = m.AddConstraintClauses(constraints);
            }

            return(m);
        }
コード例 #12
0
 public ExpressionSyntax VisitExpression(ExpressionSyntax node)
 {
     if (node is BinaryExpressionSyntax binaryExpression)
     {
         var left  = VisitExpression(binaryExpression.Left);
         var right = VisitExpression(binaryExpression.Right);
         return(SF.BinaryExpression(node.Kind(), left, right));
     }
     if (node is IdentifierNameSyntax identifierName)
     {
         return(SMS.Variables[identifierName.Identifier.Text]);
     }
     if (node is CastExpressionSyntax castExpression)
     {
         return(SF.CastExpression(castExpression.Type, VisitExpression(castExpression.Expression)));
     }
     if (node is InvocationExpressionSyntax invocationExpression)
     {
         var arguments = SF.ArgumentList();
         foreach (var a in invocationExpression.ArgumentList.Arguments)
         {
             arguments = arguments.AddArguments(VisitArgument(a));
         }
         return(SF.InvocationExpression(invocationExpression.Expression, arguments));
     }
     if (node is PrefixUnaryExpressionSyntax prefixUnaryExpression)
     {
         return(SF.PrefixUnaryExpression(node.Kind(), VisitExpression(prefixUnaryExpression.Operand)));
     }
     if (node is ParenthesizedExpressionSyntax parenthesizedExpressionSyntax)
     {
         return(SF.ParenthesizedExpression(VisitExpression(parenthesizedExpressionSyntax.Expression)));
     }
     if (node is LiteralExpressionSyntax ||
         node is MemberAccessExpressionSyntax)
     {
         return(node);
     }
     throw new NotImplementedException(node.GetType().Name);
 }
コード例 #13
0
            public override SyntaxList <StatementSyntax> VisitAssignmentStatement(VBSyntax.AssignmentStatementSyntax node)
            {
                var lhs = (ExpressionSyntax)node.Left.Accept(_nodesVisitor);
                var rhs = (ExpressionSyntax)node.Right.Accept(_nodesVisitor);

                // e.g. VB DivideAssignmentExpression "/=" is always on doubles unless you use the "\=" IntegerDivideAssignmentExpression, so need to cast in C#
                // Need the unconverted type, since the whole point is that it gets converted to a double by the operator
                if (node.IsKind(VBasic.SyntaxKind.DivideAssignmentStatement) && !node.HasOperandOfUnconvertedType("System.Double", _semanticModel))
                {
                    var doubleType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.DoubleKeyword));
                    rhs = SyntaxFactory.CastExpression(doubleType, rhs);
                }

                if (node.IsKind(VBasic.SyntaxKind.ExponentiateAssignmentStatement))
                {
                    rhs = SyntaxFactory.InvocationExpression(
                        SyntaxFactory.ParseExpression($"{nameof(Math)}.{nameof(Math.Pow)}"),
                        ExpressionSyntaxExtensions.CreateArgList(lhs, rhs));
                }
                var kind = node.Kind().ConvertToken(TokenContext.Local);

                return(SingleStatement(SyntaxFactory.AssignmentExpression(kind, lhs, rhs)));
            }
コード例 #14
0
        /// <summary>
        /// Returns syntax for the static fields of the serializer class.
        /// </summary>
        /// <param name="fields">The fields.</param>
        /// <returns>Syntax for the static fields of the serializer class.</returns>
        private static MemberDeclarationSyntax[] GenerateStaticFields(List <FieldInfoMember> fields)
        {
            var result = new List <MemberDeclarationSyntax>();

            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
            Expression <Action <TypeInfo> > getField           = _ => _.GetField(string.Empty, BindingFlags.Default);
            Expression <Action <Type> >     getTypeInfo        = _ => _.GetTypeInfo();
            Expression <Action>             getGetter          = () => SerializationManager.GetGetter(default(FieldInfo));
            Expression <Action>             getReferenceSetter = () => SerializationManager.GetReferenceSetter(default(FieldInfo));
            Expression <Action>             getValueSetter     = () => SerializationManager.GetValueSetter(default(FieldInfo));

            // Expressions for specifying binding flags.
            var bindingFlags = SyntaxFactoryExtensions.GetBindingFlagsParenthesizedExpressionSyntax(
                SyntaxKind.BitwiseOrExpression,
                BindingFlags.Instance,
                BindingFlags.NonPublic,
                BindingFlags.Public);

            // Add each field and initialize it.
            foreach (var field in fields)
            {
                var fieldInfo =
                    getField.Invoke(getTypeInfo.Invoke(SF.TypeOfExpression(field.FieldInfo.DeclaringType.GetTypeSyntax())))
                    .AddArgumentListArguments(
                        SF.Argument(field.FieldInfo.Name.GetLiteralExpression()),
                        SF.Argument(bindingFlags));
                var fieldInfoVariable =
                    SF.VariableDeclarator(field.InfoFieldName).WithInitializer(SF.EqualsValueClause(fieldInfo));
                var fieldInfoField = SF.IdentifierName(field.InfoFieldName);

                if (!field.IsGettableProperty || !field.IsSettableProperty)
                {
                    result.Add(
                        SF.FieldDeclaration(
                            SF.VariableDeclaration(typeof(FieldInfo).GetTypeSyntax()).AddVariables(fieldInfoVariable))
                        .AddModifiers(
                            SF.Token(SyntaxKind.PrivateKeyword),
                            SF.Token(SyntaxKind.StaticKeyword),
                            SF.Token(SyntaxKind.ReadOnlyKeyword)));
                }

                // Declare the getter for this field.
                if (!field.IsGettableProperty)
                {
                    var getterType =
                        typeof(Func <,>).MakeGenericType(field.FieldInfo.DeclaringType, field.FieldInfo.FieldType)
                        .GetTypeSyntax();
                    var fieldGetterVariable =
                        SF.VariableDeclarator(field.GetterFieldName)
                        .WithInitializer(
                            SF.EqualsValueClause(
                                SF.CastExpression(
                                    getterType,
                                    getGetter.Invoke().AddArgumentListArguments(SF.Argument(fieldInfoField)))));
                    result.Add(
                        SF.FieldDeclaration(SF.VariableDeclaration(getterType).AddVariables(fieldGetterVariable))
                        .AddModifiers(
                            SF.Token(SyntaxKind.PrivateKeyword),
                            SF.Token(SyntaxKind.StaticKeyword),
                            SF.Token(SyntaxKind.ReadOnlyKeyword)));
                }

                if (!field.IsSettableProperty)
                {
                    if (field.FieldInfo.DeclaringType != null && field.FieldInfo.DeclaringType.IsValueType)
                    {
                        var setterType =
                            typeof(SerializationManager.ValueTypeSetter <,>).MakeGenericType(
                                field.FieldInfo.DeclaringType,
                                field.FieldInfo.FieldType).GetTypeSyntax();

                        var fieldSetterVariable =
                            SF.VariableDeclarator(field.SetterFieldName)
                            .WithInitializer(
                                SF.EqualsValueClause(
                                    SF.CastExpression(
                                        setterType,
                                        getValueSetter.Invoke()
                                        .AddArgumentListArguments(SF.Argument(fieldInfoField)))));
                        result.Add(
                            SF.FieldDeclaration(SF.VariableDeclaration(setterType).AddVariables(fieldSetterVariable))
                            .AddModifiers(
                                SF.Token(SyntaxKind.PrivateKeyword),
                                SF.Token(SyntaxKind.StaticKeyword),
                                SF.Token(SyntaxKind.ReadOnlyKeyword)));
                    }
                    else
                    {
                        var setterType =
                            typeof(Action <,>).MakeGenericType(field.FieldInfo.DeclaringType, field.FieldInfo.FieldType)
                            .GetTypeSyntax();

                        var fieldSetterVariable =
                            SF.VariableDeclarator(field.SetterFieldName)
                            .WithInitializer(
                                SF.EqualsValueClause(
                                    SF.CastExpression(
                                        setterType,
                                        getReferenceSetter.Invoke()
                                        .AddArgumentListArguments(SF.Argument(fieldInfoField)))));

                        result.Add(
                            SF.FieldDeclaration(SF.VariableDeclaration(setterType).AddVariables(fieldSetterVariable))
                            .AddModifiers(
                                SF.Token(SyntaxKind.PrivateKeyword),
                                SF.Token(SyntaxKind.StaticKeyword),
                                SF.Token(SyntaxKind.ReadOnlyKeyword)));
                    }
                }
            }

            return(result.ToArray());
        }
コード例 #15
0
        /// <summary>
        /// Returns syntax for the deep copier method.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="fields">The fields.</param>
        /// <returns>Syntax for the deep copier method.</returns>
        private static MemberDeclarationSyntax GenerateDeepCopierMethod(Type type, List <FieldInfoMember> fields)
        {
            var originalVariable = SF.IdentifierName("original");
            var inputVariable    = SF.IdentifierName("input");
            var resultVariable   = SF.IdentifierName("result");

            var body = new List <StatementSyntax>();

            if (type.GetCustomAttribute <ImmutableAttribute>() != null)
            {
                // Immutable types do not require copying.
                body.Add(SF.ReturnStatement(originalVariable));
            }
            else
            {
                body.Add(
                    SF.LocalDeclarationStatement(
                        SF.VariableDeclaration(type.GetTypeSyntax())
                        .AddVariables(
                            SF.VariableDeclarator("input")
                            .WithInitializer(
                                SF.EqualsValueClause(
                                    SF.ParenthesizedExpression(
                                        SF.CastExpression(type.GetTypeSyntax(), originalVariable)))))));
                body.Add(
                    SF.LocalDeclarationStatement(
                        SF.VariableDeclaration(type.GetTypeSyntax())
                        .AddVariables(
                            SF.VariableDeclarator("result")
                            .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type))))));

                // Copy all members from the input to the result.
                foreach (var field in fields)
                {
                    body.Add(SF.ExpressionStatement(field.GetSetter(resultVariable, field.GetGetter(inputVariable))));
                }

                // Record this serialization.
                Expression <Action> recordObject =
                    () => SerializationContext.Current.RecordObject(default(object), default(object));
                var currentSerializationContext =
                    SyntaxFactory.AliasQualifiedName(
                        SF.IdentifierName(SF.Token(SyntaxKind.GlobalKeyword)),
                        SF.IdentifierName("Orleans"))
                    .Qualify("Serialization")
                    .Qualify("SerializationContext")
                    .Qualify("Current");
                body.Add(
                    SF.ExpressionStatement(
                        recordObject.Invoke(currentSerializationContext)
                        .AddArgumentListArguments(SF.Argument(originalVariable), SF.Argument(resultVariable))));

                body.Add(SF.ReturnStatement(resultVariable));
            }

            return
                (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "DeepCopier")
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword))
                 .AddParameterListParameters(
                     SF.Parameter(SF.Identifier("original")).WithType(typeof(object).GetTypeSyntax()))
                 .AddBodyStatements(body.ToArray())
                 .AddAttributeLists(
                     SF.AttributeList().AddAttributes(SF.Attribute(typeof(CopierMethodAttribute).GetNameSyntax()))));
        }
コード例 #16
0
        /// <summary>
        /// Returns syntax for initializing a new instance of the provided type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>Syntax for initializing a new instance of the provided type.</returns>
        private static ExpressionSyntax GetObjectCreationExpressionSyntax(Type type)
        {
            ExpressionSyntax result;
            var typeInfo = type.GetTypeInfo();

            if (typeInfo.IsValueType)
            {
                // Use the default value.
                result = SF.DefaultExpression(typeInfo.GetTypeSyntax());
            }
            else if (type.GetConstructor(Type.EmptyTypes) != null)
            {
                // Use the default constructor.
                result = SF.ObjectCreationExpression(typeInfo.GetTypeSyntax()).AddArgumentListArguments();
            }
            else
            {
                // Create an unformatted object.
#if DNXCORE50
                var bindingFlags = SyntaxFactoryExtensions.GetBindingFlagsParenthesizedExpressionSyntax(
                    SyntaxKind.BitwiseOrExpression,
                    BindingFlags.Instance,
                    BindingFlags.NonPublic,
                    BindingFlags.Public);
                var            nullLiteralExpressionArgument = SF.Argument(SF.LiteralExpression(SyntaxKind.NullLiteralExpression));
                var            typeArg         = SF.Argument(SF.TypeOfExpression(typeInfo.GetTypeSyntax()));
                var            bindingFlagsArg = SF.Argument(bindingFlags);
                var            binderArg       = nullLiteralExpressionArgument;
                ArgumentSyntax ctorArgumentsArg;
                var            cons = typeInfo.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                      .OrderBy(p => p.GetParameters().Count()).FirstOrDefault();
                var consParameters = cons != null?cons.GetParameters().Select(p => p.ParameterType).ToArray() : null;

                if (consParameters != null && consParameters.Length > 0)
                {
                    var separatedSyntaxList = new SeparatedSyntaxList <ExpressionSyntax>();
                    separatedSyntaxList = consParameters
                                          .Aggregate(separatedSyntaxList, (current, t) => current.Add(SF.DefaultExpression(t.GetTypeInfo().GetTypeSyntax())));
                    ctorArgumentsArg = SF.Argument(separatedSyntaxList.GetArrayCreationWithInitializerSyntax(
                                                       SF.PredefinedType(SF.Token(SyntaxKind.ObjectKeyword))));
                }
                else
                {
                    ctorArgumentsArg = nullLiteralExpressionArgument;
                }

                var cultureInfoArg = SF.Argument(
                    SF.IdentifierName("System").Member("Globalization").Member("CultureInfo").Member("InvariantCulture"));
                var createInstanceArguments = new []
                {
                    typeArg,
                    bindingFlagsArg,
                    binderArg,
                    ctorArgumentsArg,
                    cultureInfoArg
                };

                Expression <Func <object> > getUninitializedObject = () => Activator.CreateInstance(
                    default(Type),
                    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                    null,
                    null,
                    System.Globalization.CultureInfo.InvariantCulture);
                result = SF.CastExpression(
                    type.GetTypeSyntax(),
                    getUninitializedObject.Invoke()
                    .AddArgumentListArguments(createInstanceArguments));
#else
                Expression <Func <object> > getUninitializedObject =
                    () => FormatterServices.GetUninitializedObject(default(Type));
                result = SF.CastExpression(
                    type.GetTypeSyntax(),
                    getUninitializedObject.Invoke()
                    .AddArgumentListArguments(
                        SF.Argument(SF.TypeOfExpression(typeInfo.GetTypeSyntax()))));
#endif
            }

            return(result);
        }
コード例 #17
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))
            });
        }
コード例 #18
0
        /// <summary>
        /// Returns syntax for the deep copier method.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="fields">The fields.</param>
        /// <returns>Syntax for the deep copier method.</returns>
        private static MemberDeclarationSyntax GenerateDeepCopierMethod(Type type, List <FieldInfoMember> fields)
        {
            var originalVariable = SF.IdentifierName("original");
            var inputVariable    = SF.IdentifierName("input");
            var resultVariable   = SF.IdentifierName("result");

            var body = new List <StatementSyntax>();

            if (type.GetTypeInfo().GetCustomAttribute <ImmutableAttribute>() != null)
            {
                // Immutable types do not require copying.
                var typeName = type.GetParseableName(new TypeFormattingOptions(includeGlobal: false));
                var comment  = SF.Comment($"// No deep copy required since {typeName} is marked with the [Immutable] attribute.");
                body.Add(SF.ReturnStatement(originalVariable).WithLeadingTrivia(comment));
            }
            else
            {
                body.Add(
                    SF.LocalDeclarationStatement(
                        SF.VariableDeclaration(type.GetTypeSyntax())
                        .AddVariables(
                            SF.VariableDeclarator("input")
                            .WithInitializer(
                                SF.EqualsValueClause(
                                    SF.ParenthesizedExpression(
                                        SF.CastExpression(type.GetTypeSyntax(), originalVariable)))))));
                body.Add(
                    SF.LocalDeclarationStatement(
                        SF.VariableDeclaration(type.GetTypeSyntax())
                        .AddVariables(
                            SF.VariableDeclarator("result")
                            .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type))))));

                // Record this serialization.
                Expression <Action <ICopyContext> > recordObject =
                    ctx => ctx.RecordCopy(default(object), default(object));
                var context = SF.IdentifierName("context");
                body.Add(
                    SF.ExpressionStatement(
                        recordObject.Invoke(context)
                        .AddArgumentListArguments(SF.Argument(originalVariable), SF.Argument(resultVariable))));

                // Copy all members from the input to the result.
                foreach (var field in fields)
                {
                    body.Add(SF.ExpressionStatement(field.GetSetter(resultVariable, field.GetGetter(inputVariable, context))));
                }

                body.Add(SF.ReturnStatement(resultVariable));
            }

            return
                (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "DeepCopier")
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword))
                 .AddParameterListParameters(
                     SF.Parameter(SF.Identifier("original")).WithType(typeof(object).GetTypeSyntax()),
                     SF.Parameter(SF.Identifier("context")).WithType(typeof(ICopyContext).GetTypeSyntax()))
                 .AddBodyStatements(body.ToArray())
                 .AddAttributeLists(
                     SF.AttributeList().AddAttributes(SF.Attribute(typeof(CopierMethodAttribute).GetNameSyntax()))));
        }
コード例 #19
0
        private static MemberDeclarationSyntax GenerateConstructor(string className, List <FieldInfoMember> fields)
        {
            var body = new List <StatementSyntax>();

            Expression <Action <TypeInfo> >    getField           = _ => _.GetField(string.Empty, BindingFlags.Default);
            Expression <Action <Type> >        getTypeInfo        = _ => _.GetTypeInfo();
            Expression <Action <IFieldUtils> > getGetter          = _ => _.GetGetter(default(FieldInfo));
            Expression <Action <IFieldUtils> > getReferenceSetter = _ => _.GetReferenceSetter(default(FieldInfo));
            Expression <Action <IFieldUtils> > getValueSetter     = _ => _.GetValueSetter(default(FieldInfo));

            // Expressions for specifying binding flags.
            var bindingFlags = SyntaxFactoryExtensions.GetBindingFlagsParenthesizedExpressionSyntax(
                SyntaxKind.BitwiseOrExpression,
                BindingFlags.Instance,
                BindingFlags.NonPublic,
                BindingFlags.Public);

            var fieldUtils = SF.IdentifierName("fieldUtils");

            foreach (var field in fields)
            {
                // Get the field
                var fieldInfoField = SF.IdentifierName(field.InfoFieldName);
                var fieldInfo      =
                    getField.Invoke(getTypeInfo.Invoke(SF.TypeOfExpression(field.FieldInfo.DeclaringType.GetTypeSyntax())))
                    .AddArgumentListArguments(
                        SF.Argument(field.FieldInfo.Name.GetLiteralExpression()),
                        SF.Argument(bindingFlags));
                var fieldInfoVariable =
                    SF.VariableDeclarator(field.InfoFieldName).WithInitializer(SF.EqualsValueClause(fieldInfo));

                if (!field.IsGettableProperty || !field.IsSettableProperty)
                {
                    body.Add(SF.LocalDeclarationStatement(
                                 SF.VariableDeclaration(typeof(FieldInfo).GetTypeSyntax()).AddVariables(fieldInfoVariable)));
                }

                // Set the getter/setter of the field
                if (!field.IsGettableProperty)
                {
                    var getterType =
                        typeof(Func <,>).MakeGenericType(field.FieldInfo.DeclaringType, field.FieldInfo.FieldType)
                        .GetTypeSyntax();

                    var getterInvoke = SF.CastExpression(
                        getterType,
                        getGetter.Invoke(fieldUtils).AddArgumentListArguments(SF.Argument(fieldInfoField)));

                    body.Add(SF.ExpressionStatement(
                                 SF.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SF.IdentifierName(field.GetterFieldName), getterInvoke)));
                }
                if (!field.IsSettableProperty)
                {
                    if (field.FieldInfo.DeclaringType != null && field.FieldInfo.DeclaringType.GetTypeInfo().IsValueType)
                    {
                        var setterType =
                            typeof(ValueTypeSetter <,>).MakeGenericType(
                                field.FieldInfo.DeclaringType,
                                field.FieldInfo.FieldType).GetTypeSyntax();

                        var getValueSetterInvoke = SF.CastExpression(
                            setterType,
                            getValueSetter.Invoke(fieldUtils)
                            .AddArgumentListArguments(SF.Argument(fieldInfoField)));

                        body.Add(SF.ExpressionStatement(
                                     SF.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SF.IdentifierName(field.SetterFieldName), getValueSetterInvoke)));
                    }
                    else
                    {
                        var setterType =
                            typeof(Action <,>).MakeGenericType(field.FieldInfo.DeclaringType, field.FieldInfo.FieldType)
                            .GetTypeSyntax();

                        var getReferenceSetterInvoke = SF.CastExpression(
                            setterType,
                            getReferenceSetter.Invoke(fieldUtils)
                            .AddArgumentListArguments(SF.Argument(fieldInfoField)));

                        body.Add(SF.ExpressionStatement(
                                     SF.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SF.IdentifierName(field.SetterFieldName), getReferenceSetterInvoke)));
                    }
                }
            }

            return
                (SF.ConstructorDeclaration(className)
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
                 .AddParameterListParameters(
                     SF.Parameter(fieldUtils.Identifier).WithType(typeof(IFieldUtils).GetTypeSyntax()))
                 .AddBodyStatements(body.ToArray()));
        }
コード例 #20
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))
            });
        }