private static MethodDeclarationSyntax GenerateGetMethodNameMethod(WellKnownTypes wellKnownTypes, GrainInterfaceDescription description) { var method = wellKnownTypes.GrainReference.Method("GetMethodName"); var methodDeclaration = method.GetDeclarationSyntax().AddModifiers(Token(SyntaxKind.OverrideKeyword)); var parameters = method.Parameters; var interfaceIdArgument = parameters[0].Name.ToIdentifierName(); var methodIdArgument = parameters[1].Name.ToIdentifierName(); var callThrowMethodNotImplemented = InvocationExpression(IdentifierName("ThrowMethodNotImplemented")) .WithArgumentList(ArgumentList(SeparatedList(new[] { Argument(interfaceIdArgument), Argument(methodIdArgument) }))); // This method is used directly after its declaration to create blocks for each interface id, comprising // primarily of a nested switch statement for each of the methods in the given interface. BlockSyntax ComposeInterfaceBlock(INamedTypeSymbol interfaceType, SwitchStatementSyntax methodSwitch) { return(Block(methodSwitch.AddSections(SwitchSection() .AddLabels(DefaultSwitchLabel()) .AddStatements( ExpressionStatement(callThrowMethodNotImplemented), ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression)))))); } var interfaceCases = GrainInterfaceCommon.GenerateGrainInterfaceAndMethodSwitch( wellKnownTypes, description.Type, methodIdArgument, methodType => new StatementSyntax[] { ReturnStatement(methodType.Name.ToLiteralExpression()) }, ComposeInterfaceBlock); // Generate the default case, which will throw a NotImplementedException. var callThrowInterfaceNotImplemented = InvocationExpression(IdentifierName("ThrowInterfaceNotImplemented")) .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(interfaceIdArgument)))); var defaultCase = SwitchSection() .AddLabels(DefaultSwitchLabel()) .AddStatements( ExpressionStatement(callThrowInterfaceNotImplemented), ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression))); var throwInterfaceNotImplemented = GrainInterfaceCommon.GenerateMethodNotImplementedFunction(wellKnownTypes); var throwMethodNotImplemented = GrainInterfaceCommon.GenerateInterfaceNotImplementedFunction(wellKnownTypes); var interfaceIdSwitch = SwitchStatement(interfaceIdArgument).AddSections(interfaceCases.ToArray()).AddSections(defaultCase); return(methodDeclaration.AddBodyStatements(interfaceIdSwitch, throwInterfaceNotImplemented, throwMethodNotImplemented)); }
/// <summary> /// Generates syntax for an invoke method. /// </summary> private MethodDeclarationSyntax GenerateInvokeMethod( WellKnownTypes wellKnownTypes, INamedTypeSymbol grainType, IMethodSymbol invokeMethod, Dictionary <IMethodSymbol, GenericInvokerField> genericInvokerFields) { var parameters = invokeMethod.Parameters; var grainArgument = parameters[0].Name.ToIdentifierName(); var requestArgument = parameters[1].Name.ToIdentifierName(); var interfaceIdProperty = wellKnownTypes.InvokeMethodRequest.Property("InterfaceTypeCode"); var methodIdProperty = wellKnownTypes.InvokeMethodRequest.Property("MethodId"); var argumentsProperty = wellKnownTypes.InvokeMethodRequest.Property("Arguments"); // Store the relevant values from the request in local variables. var interfaceIdDeclaration = LocalDeclarationStatement( VariableDeclaration(wellKnownTypes.Int32.ToTypeSyntax()) .AddVariables( VariableDeclarator("interfaceTypeCode") .WithInitializer(EqualsValueClause(requestArgument.Member(interfaceIdProperty.Name))))); var interfaceIdVariable = IdentifierName("interfaceTypeCode"); var methodIdDeclaration = LocalDeclarationStatement( VariableDeclaration(wellKnownTypes.Int32.ToTypeSyntax()) .AddVariables( VariableDeclarator("methodId") .WithInitializer(EqualsValueClause(requestArgument.Member(methodIdProperty.Name))))); var methodIdVariable = IdentifierName("methodId"); var argumentsDeclaration = LocalDeclarationStatement( VariableDeclaration(IdentifierName("var")) .AddVariables( VariableDeclarator("arguments") .WithInitializer(EqualsValueClause(requestArgument.Member(argumentsProperty.Name))))); var argumentsVariable = IdentifierName("arguments"); var methodDeclaration = invokeMethod.GetDeclarationSyntax() .AddModifiers(Token(SyntaxKind.AsyncKeyword)) .AddBodyStatements(interfaceIdDeclaration, methodIdDeclaration, argumentsDeclaration); var callThrowMethodNotImplemented = InvocationExpression(IdentifierName("ThrowMethodNotImplemented")) .WithArgumentList(ArgumentList(SeparatedList(new[] { Argument(interfaceIdVariable), Argument(methodIdVariable) }))); // This method is used directly after its declaration to create blocks for each interface id, comprising // primarily of a nested switch statement for each of the methods in the given interface. BlockSyntax ComposeInterfaceBlock(INamedTypeSymbol interfaceType, SwitchStatementSyntax methodSwitch) { ExpressionSyntax targetObject; if (grainType.HasInterface(wellKnownTypes.IGrainExtension)) { targetObject = InvocationExpression(grainArgument.Member("GetGrainExtension", interfaceType), ArgumentList()); } else { targetObject = grainArgument.Member("GrainInstance"); } var typedGrainDeclaration = LocalDeclarationStatement( VariableDeclaration(IdentifierName("var")) .AddVariables( VariableDeclarator("casted") .WithInitializer(EqualsValueClause(ParenthesizedExpression(CastExpression(interfaceType.ToTypeSyntax(), targetObject)))))); return(Block(typedGrainDeclaration, methodSwitch.AddSections(SwitchSection() .AddLabels(DefaultSwitchLabel()) .AddStatements( ExpressionStatement(callThrowMethodNotImplemented), ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression)))))); } var interfaceCases = GrainInterfaceCommon.GenerateGrainInterfaceAndMethodSwitch( wellKnownTypes, grainType, methodIdVariable, methodType => GenerateInvokeForMethod(wellKnownTypes, IdentifierName("casted"), methodType, argumentsVariable, genericInvokerFields), ComposeInterfaceBlock); var throwInterfaceNotImplemented = GrainInterfaceCommon.GenerateMethodNotImplementedFunction(wellKnownTypes); var throwMethodNotImplemented = GrainInterfaceCommon.GenerateInterfaceNotImplementedFunction(wellKnownTypes); // Generate the default case, which will call the above local function to throw . var callThrowInterfaceNotImplemented = InvocationExpression(IdentifierName("ThrowInterfaceNotImplemented")) .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(interfaceIdVariable)))); var defaultCase = SwitchSection() .AddLabels(DefaultSwitchLabel()) .AddStatements( ExpressionStatement(callThrowInterfaceNotImplemented), ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression))); var interfaceIdSwitch = SwitchStatement(interfaceIdVariable).AddSections(interfaceCases.ToArray()).AddSections(defaultCase); return(methodDeclaration.AddBodyStatements(interfaceIdSwitch, throwInterfaceNotImplemented, throwMethodNotImplemented)); }