ServiceGenerator.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Google.ProtocolBuffers.Descriptors;
  5. namespace Google.ProtocolBuffers.ProtoGen {
  6. internal class ServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator {
  7. private enum RequestOrResponse {
  8. Request,
  9. Response
  10. }
  11. internal ServiceGenerator(ServiceDescriptor descriptor)
  12. : base(descriptor) {
  13. }
  14. public void Generate(TextGenerator writer) {
  15. writer.WriteLine("{0} abstract class {1} : pb::IService {{", ClassAccessLevel, Descriptor.Name);
  16. writer.Indent();
  17. foreach (MethodDescriptor method in Descriptor.Methods) {
  18. writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel, Helpers.UnderscoresToPascalCase(method.Name));
  19. writer.WriteLine(" pb::IRpcController controller,");
  20. writer.WriteLine(" {0} request,", DescriptorUtil.GetClassName(method.InputType));
  21. writer.WriteLine(" global::System.Action<{0}> done);", DescriptorUtil.GetClassName(method.OutputType));
  22. }
  23. // Generate Descriptor and DescriptorForType.
  24. writer.WriteLine();
  25. writer.WriteLine("{0} static pbd::ServiceDescriptor Descriptor {{", ClassAccessLevel);
  26. writer.WriteLine(" get {{ return {0}.Descriptor.Services[{1}]; }}",
  27. DescriptorUtil.GetUmbrellaClassName(Descriptor.File), Descriptor.Index);
  28. writer.WriteLine("}");
  29. writer.WriteLine("{0} pbd::ServiceDescriptor DescriptorForType {{", ClassAccessLevel);
  30. writer.WriteLine(" get { return Descriptor; }");
  31. writer.WriteLine("}");
  32. GenerateCallMethod(writer);
  33. GenerateGetPrototype(RequestOrResponse.Request, writer);
  34. GenerateGetPrototype(RequestOrResponse.Response, writer);
  35. GenerateStub(writer);
  36. writer.Outdent();
  37. writer.WriteLine("}");
  38. }
  39. private void GenerateCallMethod(TextGenerator writer) {
  40. writer.WriteLine();
  41. writer.WriteLine("public void CallMethod(", ClassAccessLevel);
  42. writer.WriteLine(" pbd::MethodDescriptor method,");
  43. writer.WriteLine(" pb::IRpcController controller,");
  44. writer.WriteLine(" pb::IMessage request,");
  45. writer.WriteLine(" global::System.Action<pb::IMessage> done) {");
  46. writer.Indent();
  47. writer.WriteLine("if (method.Service != Descriptor) {");
  48. writer.WriteLine(" throw new global::System.ArgumentException(");
  49. writer.WriteLine(" \"Service.CallMethod() given method descriptor for wrong service type.\");");
  50. writer.WriteLine("}");
  51. writer.WriteLine("switch(method.Index) {");
  52. writer.Indent();
  53. foreach (MethodDescriptor method in Descriptor.Methods) {
  54. writer.WriteLine("case {0}:", method.Index);
  55. writer.WriteLine(" this.{0}(controller, ({0}) request,",
  56. Helpers.UnderscoresToPascalCase(method.Name), DescriptorUtil.GetClassName(method.InputType));
  57. writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", DescriptorUtil.GetClassName(method.OutputType));
  58. writer.WriteLine(" done));");
  59. writer.WriteLine(" return;");
  60. }
  61. writer.WriteLine("default:");
  62. writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
  63. writer.Outdent();
  64. writer.WriteLine("}");
  65. writer.Outdent();
  66. writer.WriteLine("}");
  67. writer.WriteLine();
  68. }
  69. private void GenerateGetPrototype(RequestOrResponse which, TextGenerator writer) {
  70. writer.WriteLine("public pb::IMessage Get{0}Prototype(pbd::MethodDescriptor method) {{", which);
  71. writer.Indent();
  72. writer.WriteLine("if (method.Service != Descriptor) {");
  73. writer.WriteLine(" throw new global::System.ArgumentException(");
  74. writer.WriteLine(" \"Service.Get{0}Prototype() given method descriptor for wrong service type.\");", which);
  75. writer.WriteLine("}");
  76. writer.WriteLine("switch(method.Index) {");
  77. writer.Indent();
  78. foreach (MethodDescriptor method in Descriptor.Methods) {
  79. writer.WriteLine("case {0}:", method.Index);
  80. writer.WriteLine(" return {0}.DefaultInstance;",
  81. DescriptorUtil.GetClassName(which == RequestOrResponse.Request ? method.InputType : method.OutputType));
  82. }
  83. writer.WriteLine("default:");
  84. writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
  85. writer.Outdent();
  86. writer.WriteLine("}");
  87. writer.Outdent();
  88. writer.WriteLine("}");
  89. writer.WriteLine();
  90. }
  91. private void GenerateStub(TextGenerator writer) {
  92. writer.WriteLine("public static Stub CreateStub(pb::IRpcChannel channel) {");
  93. writer.WriteLine(" return new Stub(channel);");
  94. writer.WriteLine("}");
  95. writer.WriteLine();
  96. writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, DescriptorUtil.GetClassName(Descriptor));
  97. writer.Indent();
  98. writer.WriteLine("internal Stub(pb::IRpcChannel channel) {");
  99. writer.WriteLine(" this.channel = channel;");
  100. writer.WriteLine("}");
  101. writer.WriteLine();
  102. writer.WriteLine("private readonly pb::IRpcChannel channel;");
  103. writer.WriteLine();
  104. writer.WriteLine("public pb::IRpcChannel Channel {");
  105. writer.WriteLine(" get { return channel; }");
  106. writer.WriteLine("}");
  107. foreach (MethodDescriptor method in Descriptor.Methods) {
  108. writer.WriteLine();
  109. writer.WriteLine("public override void {0}(", Helpers.UnderscoresToPascalCase(method.Name));
  110. writer.WriteLine(" pb::IRpcController controller,");
  111. writer.WriteLine(" {0} request,", DescriptorUtil.GetClassName(method.InputType));
  112. writer.WriteLine(" global::System.Action<{0}> done) {{", DescriptorUtil.GetClassName(method.OutputType));
  113. writer.Indent();
  114. writer.WriteLine("channel.CallMethod(Descriptor.Methods[{0}],", method.Index);
  115. writer.WriteLine(" controller, request, {0}.DefaultInstance,", DescriptorUtil.GetClassName(method.OutputType));
  116. writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));",
  117. DescriptorUtil.GetClassName(method.OutputType));
  118. writer.Outdent();
  119. writer.WriteLine("}");
  120. }
  121. writer.Outdent();
  122. writer.WriteLine("}");
  123. }
  124. }
  125. }