private static ClassDeclarationSyntax GenerateReadGrain(ClassDeclarationSyntax grainClass, ITypeSymbol swmrInterface, int readReplicaCount)
        {
            string readGrainName             = SwmrUtils.GetReadInterfaceName(grainClass.Identifier.Text);
            string readerInterfaceName       = SwmrUtils.GetReadInterfaceName(swmrInterface.Name);
            ClassDeclarationSyntax readGrain = GenerateClassSqueleton(readGrainName).WithAttributeLists(AttributeUtils.AttributeListList(AttributeUtils.Attribute(StatelessWorkerAttributeName))).WithBaseList(RoslynUtils.BaseList(new[] { "Grain", readerInterfaceName }));

            readGrain = RoslynUtils.AddField(readGrain, "ITopology<string>", "_topology");
            readGrain = readGrain.AddMembers(GenerateOnActivateAsyncMethod(readReplicaCount));

            string readReplicaInterfaceName = SwmrUtils.GetReadReplicaInterfaceName(swmrInterface.Name);

            foreach (ISymbol member in swmrInterface.GetMembers())
            {
                IMethodSymbol methodSymbol = member as IMethodSymbol;
                if (methodSymbol == null || !IsReadOnlyMethod(methodSymbol))
                {
                    continue;
                }

                MethodInspector methodInspector = new MethodInspector(methodSymbol);
                string          parameters      = "string sessionId";
                if (methodInspector.MethodParams.Any())
                {
                    parameters = string.Join(", ", methodInspector.MethodParams.Select(param => string.Format("{0} {1}", param.Value, param.Key))) + " ," + parameters;
                }

                var method = RoslynUtils.ParseMethod(string.Format(
                                                         @"
        public {0} {1}({2})
        {{
            string sessionNode = _topology.GetNode(sessionId);
            var readReplica = GrainFactory.GetGrain<{3}>(sessionNode);
            return readReplica.{1}({4});
        }}", methodInspector.ReturnType, methodInspector.MethodName, parameters, readReplicaInterfaceName, string.Join(", ", methodInspector.MethodParams.Keys)));

                readGrain =
                    readGrain.AddMembers(
                        method.WithLeadingTrivia(SF.EndOfLine("")));
            }
            return(readGrain);
        }
Ejemplo n.º 2
0
        public async Task <CodeGenResult> CodeGen(Workspace workspace, Project project)
        {
            CompilationUnitSyntax cu = SF.CompilationUnit();

            var usings = new HashSet <string>();

            foreach (Document document in project.Documents)
            {
                SyntaxTree syntaxTree = await document.GetSyntaxTreeAsync();

                _semanticModel = await document.GetSemanticModelAsync();

                IEnumerable <InterfaceDeclarationSyntax> interfaces =
                    syntaxTree.GetRoot().DescendantNodes().OfType <InterfaceDeclarationSyntax>();

                foreach (var interfaceNode in interfaces)
                {
                    if (!RoslynUtils.IsPublic(interfaceNode))
                    {
                        continue;
                    }

                    AttributeSyntax swmrAttribute = AttributeUtils.SelectAttributeOfType(interfaceNode.AttributeLists, typeof(SingleWriterMultipleReadersAttribute), _semanticModel);

                    if (swmrAttribute == null)
                    {
                        continue;
                    }

                    var namespaceNode = interfaceNode.Parent as NamespaceDeclarationSyntax;
                    if (namespaceNode == null)
                    {
                        throw new Exception("A grain interface must be declared inside a namespace");
                    }

                    usings.UnionWith(syntaxTree.GetRoot().DescendantNodes().OfType <UsingDirectiveSyntax>().Select(usingDirective => usingDirective.Name.ToString()));

                    var methods      = RoslynUtils.GetMethodDeclarations(interfaceNode);
                    var readMethods  = SwmrUtils.GetReadOnlyMethods(methods, _semanticModel);
                    var writeMethods = methods.Except(readMethods).Where(method => new MethodInspector(method).MethodName != "GetState");

                    readMethods = SwmrUtils.RemoveReadOnlyAttribute(readMethods, _semanticModel);

                    string grainInterfaceName = interfaceNode.Identifier.Text;
                    var    readReplicaMethods = new List <MethodDeclarationSyntax>(readMethods)
                    {
                        GenerateSetStateMethod()
                    };

                    InterfaceDeclarationSyntax readReplicaInterface =
                        GenerateInterface(SwmrUtils.GetReadReplicaInterfaceName(grainInterfaceName), readReplicaMethods,
                                          interfaceNode.BaseList);

                    readMethods  = SwmrUtils.AddSessionIdParameter(readMethods);
                    writeMethods = SwmrUtils.AddSessionIdParameter(writeMethods);

                    string readerInterfaceName = SwmrUtils.GetReadInterfaceName(grainInterfaceName);
                    string writerInterfaceName = SwmrUtils.GetWriteInterfaceName(grainInterfaceName);

                    InterfaceDeclarationSyntax readerInterface = GenerateInterface(readerInterfaceName, readMethods,
                                                                                   interfaceNode.BaseList);
                    InterfaceDeclarationSyntax writerInterface = GenerateInterface(writerInterfaceName, writeMethods,
                                                                                   interfaceNode.BaseList);

                    string fullNameSpace = _semanticModel.GetDeclaredSymbol(namespaceNode).ToString();
                    NamespaceDeclarationSyntax namespaceDclr = SF.NamespaceDeclaration(SF.IdentifierName(fullNameSpace)).WithUsings(namespaceNode.Usings);

                    namespaceDclr = namespaceDclr.AddMembers(readerInterface, writerInterface, readReplicaInterface);

                    usings.UnionWith(namespaceNode.Usings.Select(@using => @using.Name.ToString()));
                    usings.Remove("ETG.Orleans.Attributes");
                    cu = cu.AddMembers(namespaceDclr);
                }
            }
            return(new CodeGenResult(Formatter.Format(cu, workspace).ToString(), usings));
        }