Esempio n. 1
0
            private Dictionary <int, MethodInfo> GetGrainMethods()
            {
                var grainMethods = new Dictionary <int, MethodInfo>();

                foreach (var interfaceMethodInfo in GrainInterfaceData.GetMethods(InterfaceType))
                {
                    ParameterInfo[] parameters = interfaceMethodInfo.GetParameters();
                    var             args       = new Type[parameters.Length];

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        args[i] = parameters[i].ParameterType;
                    }

                    MethodInfo methodInfo = InterfaceType.GetMethod(interfaceMethodInfo.Name, args) ?? interfaceMethodInfo;

                    if (IsGrainMethod(methodInfo))
                    {
                        grainMethods.Add(GrainInterfaceData.ComputeMethodId(methodInfo), methodInfo);
                    }
                }
                return(grainMethods);
            }
Esempio n. 2
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());
        }
Esempio n. 3
0
        internal void AddReferenceClass(GrainInterfaceData interfaceData)
        {
            bool isObserver = IsObserver(interfaceData.Type);
            CodeTypeParameterCollection genericTypeParam = interfaceData.GenericTypeParams;

            // Declare factory class
            var factoryClass = new CodeTypeDeclaration(interfaceData.FactoryClassBaseName);

            if (genericTypeParam != null)
            {
                factoryClass.TypeParameters.AddRange(genericTypeParam);
            }

            factoryClass.IsClass        = true;
            factoryClass.TypeAttributes = interfaceData.Type.IsPublic ? TypeAttributes.Public : TypeAttributes.NotPublic;
            MarkAsGeneratedCode(factoryClass);
            AddFactoryMethods(interfaceData, factoryClass);
            AddCastMethods(interfaceData, true, factoryClass);

            if (ShouldGenerateObjectRefFactory(interfaceData))
            {
                AddCreateObjectReferenceMethods(interfaceData, factoryClass);
            }

            int factoryClassIndex = ReferencedNamespace.Types.Add(factoryClass);

            var referenceClass = new CodeTypeDeclaration(interfaceData.ReferenceClassBaseName);

            if (genericTypeParam != null)
            {
                referenceClass.TypeParameters.AddRange(genericTypeParam);
            }
            referenceClass.IsClass = true;

            referenceClass.BaseTypes.Add(new CodeTypeReference(typeof(GrainReference), CodeTypeReferenceOptions.GlobalReference));
            referenceClass.BaseTypes.Add(new CodeTypeReference(typeof(IAddressable), CodeTypeReferenceOptions.GlobalReference));
            var tref = new CodeTypeReference(interfaceData.Type);

            if (genericTypeParam != null)
            {
                foreach (CodeTypeParameter tp in genericTypeParam)
                {
                    tref.TypeArguments.Add(tp.Name);
                }
            }

            referenceClass.BaseTypes.Add(tref);

            MarkAsGeneratedCode(referenceClass);
            referenceClass.TypeAttributes = TypeAttributes.NestedAssembly;
            referenceClass.CustomAttributes.Add(
                new CodeAttributeDeclaration(new CodeTypeReference(typeof(SerializableAttribute))));

            referenceClass.CustomAttributes.Add(
                new CodeAttributeDeclaration(
                    new CodeTypeReference(typeof(GrainReferenceAttribute), CodeTypeReferenceOptions.GlobalReference),
                    new CodeAttributeArgument(
                        new CodePrimitiveExpression(interfaceData.Type.Namespace + "." + TypeUtils.GetParameterizedTemplateName((interfaceData.Type))))));

            var baseReferenceConstructor2 = new CodeConstructor {
                Attributes = MemberAttributes.FamilyOrAssembly
            };

            baseReferenceConstructor2.Parameters.Add(new CodeParameterDeclarationExpression(
                                                         new CodeTypeReference(typeof(GrainReference), CodeTypeReferenceOptions.GlobalReference), "reference"));

            baseReferenceConstructor2.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("reference"));
            referenceClass.Members.Add(baseReferenceConstructor2);

            var baseReferenceConstructor3 = new CodeConstructor {
                Attributes = MemberAttributes.FamilyOrAssembly
            };

            baseReferenceConstructor3.Parameters.Add(new CodeParameterDeclarationExpression("SerializationInfo", "info"));
            baseReferenceConstructor3.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("info"));
            baseReferenceConstructor3.Parameters.Add(new CodeParameterDeclarationExpression("StreamingContext", "context"));
            baseReferenceConstructor3.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("context"));
            referenceClass.Members.Add(baseReferenceConstructor3);

            var grainRef     = new CodeTypeReference(typeof(GrainReference), CodeTypeReferenceOptions.GlobalReference);
            var refClassName = FixupTypeName(interfaceData.ReferenceClassName);

            // Copier, serializer, and deserializer for this type
            var copier = SerializerGenerationUtilities.GenerateCopier("_Copier", refClassName, genericTypeParam);

            copier.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeCastExpression(refClassName,
                                           new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(grainRef), "CopyGrainReference", new CodeVariableReferenceExpression("input")))));
            referenceClass.Members.Add(copier);

            var serializer = SerializerGenerationUtilities.GenerateSerializer("_Serializer", refClassName, genericTypeParam);

            serializer.Statements.Add(
                new CodeMethodInvokeExpression(
                    new CodeTypeReferenceExpression(grainRef),
                    "SerializeGrainReference", new CodeVariableReferenceExpression("input"),
                    new CodeArgumentReferenceExpression("stream"),
                    new CodeArgumentReferenceExpression("expected")));
            referenceClass.Members.Add(serializer);

            var deserializer = SerializerGenerationUtilities.GenerateDeserializer("_Deserializer", refClassName, genericTypeParam);

            deserializer.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeTypeReferenceExpression(refClassName),
                        "Cast",
                        new CodeCastExpression(grainRef,
                                               new CodeMethodInvokeExpression(
                                                   new CodeTypeReferenceExpression(grainRef),
                                                   "DeserializeGrainReference",
                                                   new CodeArgumentReferenceExpression("expected"), new CodeArgumentReferenceExpression("stream"))))));
            referenceClass.Members.Add(deserializer);

            // this private class is the "implementation class" for the interface reference type
            ReferencedNamespace.Types[factoryClassIndex].Members.Add(referenceClass);

            AddCastMethods(interfaceData, false, referenceClass);

            var interfaceId       = GrainInterfaceData.GetGrainInterfaceId(interfaceData.Type);
            var interfaceIdMethod = new CodeMemberProperty
            {
                Name       = "InterfaceId",
                Type       = new CodeTypeReference(typeof(int)),
                Attributes = MemberAttributes.Family | MemberAttributes.Override,
                HasSet     = false,
                HasGet     = true
            };

            interfaceIdMethod.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(interfaceId)));
            referenceClass.Members.Add(interfaceIdMethod);


            var left = new CodeBinaryOperatorExpression(
                new CodeArgumentReferenceExpression("interfaceId"),
                CodeBinaryOperatorType.ValueEquality,
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "InterfaceId"));

            var interfaceList = GrainInterfaceData.GetRemoteInterfaces(interfaceData.Type);

            foreach (int iid in interfaceList.Keys)
            {
                if (iid == interfaceId)
                {
                    continue;                     // already covered the main interfaces
                }
                left = new CodeBinaryOperatorExpression(
                    left,
                    CodeBinaryOperatorType.BooleanOr,
                    new CodeBinaryOperatorExpression(
                        new CodeArgumentReferenceExpression("interfaceId"),
                        CodeBinaryOperatorType.ValueEquality,
                        new CodePrimitiveExpression(iid)));
            }

            var interfaceIsCompatibleMethod = new CodeMemberMethod
            {
                Name       = "IsCompatible",
                ReturnType = new CodeTypeReference(typeof(bool))
            };

            interfaceIsCompatibleMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "interfaceId"));
            interfaceIsCompatibleMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override;
            interfaceIsCompatibleMethod.Statements.Add(new CodeMethodReturnStatement(left));
            referenceClass.Members.Add(interfaceIsCompatibleMethod);

            var interfaceNameMethod = new CodeMemberProperty
            {
                Name       = "InterfaceName",
                Type       = new CodeTypeReference(typeof(string)),
                Attributes = MemberAttributes.Family | MemberAttributes.Override,
                HasSet     = false,
                HasGet     = true
            };

            interfaceNameMethod.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(FixupTypeName(interfaceData.TypeFullName))));
            referenceClass.Members.Add(interfaceNameMethod);

            var invokerClassName = interfaceData.InvokerClassName;

            var getMethodNameMethod = new CodeMemberMethod
            {
                Name       = "GetMethodName",
                ReturnType = new CodeTypeReference(typeof(string))
            };

            getMethodNameMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "interfaceId"));
            getMethodNameMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "methodId"));
            getMethodNameMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            var methodInvokerName = string.Format("{0}.GetMethodName", FixupTypeName(invokerClassName));

            getMethodNameMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        null, methodInvokerName,
                        new CodeArgumentReferenceExpression("interfaceId"),
                        new CodeArgumentReferenceExpression("methodId"))));
            referenceClass.Members.Add(getMethodNameMethod);

            CodeTypeDeclaration invokerClass = GetInvokerClass(interfaceData, true);

            invokerClass.TypeAttributes = TypeAttributes.NotPublic;
            ReferencedNamespace.Types.Add(invokerClass);

            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Net"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Runtime.Serialization"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Runtime.Serialization.Formatters.Binary"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.IO"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));

            MethodInfo[] methods = GrainInterfaceData.GetMethods(interfaceData.Type);
            AddMethods(methods, referenceClass, genericTypeParam, isObserver);
        }
Esempio n. 4
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());
        }