ProtocolImporter.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. //
  2. // System.Web.Services.Description.ProtocolImporter.cs
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. //
  8. // Copyright (C) Tim Coleman, 2002
  9. //
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. using System;
  31. using System.CodeDom;
  32. using System.CodeDom.Compiler;
  33. using System.Web.Services;
  34. using System.Web.Services.Protocols;
  35. using System.Xml.Serialization;
  36. using System.Xml;
  37. using System.Xml.Schema;
  38. using System.Collections;
  39. using System.Configuration;
  40. namespace System.Web.Services.Description {
  41. public abstract class ProtocolImporter {
  42. #region Fields
  43. Binding binding;
  44. string className;
  45. CodeIdentifiers classNames;
  46. CodeNamespace codeNamespace;
  47. CodeCompileUnit codeCompileUnit;
  48. CodeTypeDeclaration codeTypeDeclaration;
  49. Message inputMessage;
  50. string methodName;
  51. Operation operation;
  52. OperationBinding operationBinding;
  53. Message outputMessage;
  54. Port port;
  55. PortType portType;
  56. string protocolName;
  57. Service service;
  58. ServiceDescriptionImportWarnings warnings = (ServiceDescriptionImportWarnings)0;
  59. ServiceDescriptionImporter descriptionImporter;
  60. ImportInfo iinfo;
  61. XmlSchemas xmlSchemas;
  62. XmlSchemas soapSchemas;
  63. #if NET_2_0
  64. ArrayList asyncTypes = new ArrayList ();
  65. #endif
  66. #endregion // Fields
  67. #region Constructors
  68. protected ProtocolImporter ()
  69. {
  70. }
  71. #endregion // Constructors
  72. #region Properties
  73. [MonoTODO]
  74. public XmlSchemas AbstractSchemas {
  75. get { return descriptionImporter.Schemas; }
  76. }
  77. public Binding Binding {
  78. get { return binding; }
  79. }
  80. public string ClassName {
  81. get { return className; }
  82. }
  83. public CodeIdentifiers ClassNames {
  84. get { return classNames; }
  85. }
  86. public CodeNamespace CodeNamespace {
  87. get { return codeNamespace; }
  88. }
  89. public CodeTypeDeclaration CodeTypeDeclaration {
  90. get { return codeTypeDeclaration; }
  91. }
  92. [MonoTODO]
  93. public XmlSchemas ConcreteSchemas {
  94. get { return descriptionImporter.Schemas; }
  95. }
  96. public Message InputMessage {
  97. get { return inputMessage; }
  98. }
  99. public string MethodName {
  100. get { return methodName; }
  101. }
  102. public Operation Operation {
  103. get { return operation; }
  104. }
  105. public OperationBinding OperationBinding {
  106. get { return operationBinding; }
  107. }
  108. public Message OutputMessage {
  109. get { return outputMessage; }
  110. }
  111. public Port Port {
  112. get { return port; }
  113. }
  114. public PortType PortType {
  115. get { return portType; }
  116. }
  117. public abstract string ProtocolName {
  118. get;
  119. }
  120. public XmlSchemas Schemas {
  121. get { return descriptionImporter.Schemas; }
  122. }
  123. public Service Service {
  124. get { return service; }
  125. }
  126. public ServiceDescriptionCollection ServiceDescriptions {
  127. get { return descriptionImporter.ServiceDescriptions; }
  128. }
  129. public ServiceDescriptionImportStyle Style {
  130. get { return descriptionImporter.Style; }
  131. }
  132. public ServiceDescriptionImportWarnings Warnings {
  133. get { return warnings; }
  134. set { warnings = value; }
  135. }
  136. internal ImportInfo ImportInfo
  137. {
  138. get { return iinfo; }
  139. }
  140. internal XmlSchemas LiteralSchemas
  141. {
  142. get { return xmlSchemas; }
  143. }
  144. internal XmlSchemas EncodedSchemas
  145. {
  146. get { return soapSchemas; }
  147. }
  148. #if NET_2_0
  149. internal CodeGenerationOptions CodeGenerationOptions {
  150. get { return descriptionImporter.CodeGenerationOptions; }
  151. }
  152. internal ICodeGenerator CodeGenerator {
  153. get { return descriptionImporter.CodeGenerator; }
  154. }
  155. internal ImportContext ImportContext {
  156. get { return descriptionImporter.Context; }
  157. }
  158. #endif
  159. #endregion // Properties
  160. #region Methods
  161. internal bool Import (ServiceDescriptionImporter descriptionImporter, CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit, ArrayList importInfo)
  162. {
  163. this.descriptionImporter = descriptionImporter;
  164. this.classNames = new CodeIdentifiers();;
  165. this.codeNamespace = codeNamespace;
  166. this.codeCompileUnit = codeCompileUnit;
  167. warnings = (ServiceDescriptionImportWarnings) 0;
  168. bool found = false;
  169. ClasifySchemas (importInfo);
  170. BeginNamespace ();
  171. foreach (ImportInfo info in importInfo)
  172. {
  173. foreach (Service service in info.ServiceDescription.Services)
  174. {
  175. this.service = service;
  176. int bindingCount = 0;
  177. foreach (Port port in service.Ports)
  178. {
  179. binding = ServiceDescriptions.GetBinding (port.Binding);
  180. if (IsBindingSupported ()) bindingCount ++;
  181. }
  182. foreach (Port port in service.Ports)
  183. {
  184. this.iinfo = info;
  185. this.port = port;
  186. binding = ServiceDescriptions.GetBinding (port.Binding);
  187. if (!IsBindingSupported ()) continue;
  188. found = true;
  189. ImportPortBinding (bindingCount > 1);
  190. }
  191. }
  192. }
  193. EndNamespace ();
  194. if (!found) warnings = ServiceDescriptionImportWarnings.NoCodeGenerated;
  195. return true;
  196. }
  197. void ImportPortBinding (bool multipleBindings)
  198. {
  199. if (multipleBindings) className = port.Name;
  200. else className = service.Name;
  201. className = classNames.AddUnique (CodeIdentifier.MakeValid (className), port);
  202. className = className.Replace ("_x0020_", ""); // MS.NET seems to do this
  203. try
  204. {
  205. portType = ServiceDescriptions.GetPortType (binding.Type);
  206. if (portType == null) throw new Exception ("Port type not found: " + binding.Type);
  207. CodeTypeDeclaration codeClass = BeginClass ();
  208. codeTypeDeclaration = codeClass;
  209. AddCodeType (codeClass, port.Documentation);
  210. codeClass.Attributes = MemberAttributes.Public;
  211. if (service.Documentation != null && service.Documentation != "")
  212. AddComments (codeClass, service.Documentation);
  213. if (Style == ServiceDescriptionImportStyle.Client) {
  214. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Diagnostics.DebuggerStepThroughAttribute");
  215. AddCustomAttribute (codeClass, att, true);
  216. att = new CodeAttributeDeclaration ("System.ComponentModel.DesignerCategoryAttribute");
  217. att.Arguments.Add (GetArg ("code"));
  218. AddCustomAttribute (codeClass, att, true);
  219. }
  220. else
  221. codeClass.TypeAttributes = System.Reflection.TypeAttributes.Abstract | System.Reflection.TypeAttributes.Public;
  222. if (binding.Operations.Count == 0) {
  223. warnings |= ServiceDescriptionImportWarnings.NoMethodsGenerated;
  224. return;
  225. }
  226. foreach (OperationBinding oper in binding.Operations)
  227. {
  228. operationBinding = oper;
  229. operation = FindPortOperation ();
  230. if (operation == null) throw new Exception ("Operation " + operationBinding.Name + " not found in portType " + PortType.Name);
  231. foreach (OperationMessage omsg in operation.Messages)
  232. {
  233. Message msg = ServiceDescriptions.GetMessage (omsg.Message);
  234. if (msg == null) throw new Exception ("Message not found: " + omsg.Message);
  235. if (omsg is OperationInput)
  236. inputMessage = msg;
  237. else
  238. outputMessage = msg;
  239. }
  240. CodeMemberMethod method = GenerateMethod ();
  241. if (method != null)
  242. {
  243. methodName = method.Name;
  244. if (operation.Documentation != null && operation.Documentation != "")
  245. AddComments (method, operation.Documentation);
  246. #if NET_2_0
  247. if (Style == ServiceDescriptionImportStyle.Client)
  248. AddAsyncMembers (method.Name, method);
  249. #endif
  250. }
  251. }
  252. #if NET_2_0
  253. if (Style == ServiceDescriptionImportStyle.Client)
  254. AddAsyncTypes ();
  255. #endif
  256. EndClass ();
  257. }
  258. catch (InvalidOperationException ex)
  259. {
  260. warnings |= ServiceDescriptionImportWarnings.NoCodeGenerated;
  261. UnsupportedBindingWarning (ex.Message);
  262. }
  263. }
  264. Operation FindPortOperation ()
  265. {
  266. string inMessage = null;
  267. string outMessage = null;
  268. int numMsg = 1;
  269. if (operationBinding.Input == null) throw new InvalidOperationException ("Input operation binding not found");
  270. inMessage = (operationBinding.Input.Name != null) ? operationBinding.Input.Name : operationBinding.Name;
  271. if (operationBinding.Output != null) {
  272. outMessage = (operationBinding.Output.Name != null) ? operationBinding.Output.Name : operationBinding.Name;
  273. numMsg++;
  274. }
  275. string operName = operationBinding.Name;
  276. Operation foundOper = null;
  277. foreach (Operation oper in PortType.Operations)
  278. {
  279. if (oper.Name == operName)
  280. {
  281. int hits = 0;
  282. foreach (OperationMessage omsg in oper.Messages)
  283. {
  284. if (omsg is OperationInput && GetOperMessageName (omsg, operName) == inMessage) hits++;
  285. if (omsg is OperationOutput && GetOperMessageName (omsg, operName) == outMessage) hits++;
  286. }
  287. if (hits == numMsg) return oper;
  288. foundOper = oper;
  289. }
  290. }
  291. return foundOper;
  292. }
  293. string GetOperMessageName (OperationMessage msg, string operName)
  294. {
  295. if (msg.Name == null) return operName;
  296. else return msg.Name;
  297. }
  298. internal string GetServiceUrl (string location)
  299. {
  300. if (ImportInfo.AppSettingUrlKey == null || ImportInfo.AppSettingUrlKey == string.Empty)
  301. return location;
  302. else
  303. {
  304. string url;
  305. if (Style == ServiceDescriptionImportStyle.Server) throw new InvalidOperationException ("Cannot set appSettingUrlKey if Style is Server");
  306. url = ConfigurationSettings.AppSettings [ImportInfo.AppSettingUrlKey];
  307. if (ImportInfo.AppSettingBaseUrl != null && ImportInfo.AppSettingBaseUrl != string.Empty)
  308. url += "/" + ImportInfo.AppSettingBaseUrl + "/" + location;
  309. return url;
  310. }
  311. }
  312. void ClasifySchemas (ArrayList importInfo)
  313. {
  314. // I don't like this, but I could not find any other way of clasifying
  315. // schemas between encoded and literal.
  316. xmlSchemas = new XmlSchemas ();
  317. soapSchemas = new XmlSchemas ();
  318. foreach (ImportInfo info in importInfo)
  319. {
  320. foreach (Service service in info.ServiceDescription.Services)
  321. {
  322. foreach (Port port in service.Ports)
  323. {
  324. this.iinfo = info;
  325. this.port = port;
  326. binding = ServiceDescriptions.GetBinding (port.Binding);
  327. if (binding == null) continue;
  328. portType = ServiceDescriptions.GetPortType (binding.Type);
  329. if (portType == null) continue;
  330. foreach (OperationBinding oper in binding.Operations)
  331. {
  332. operationBinding = oper;
  333. operation = FindPortOperation ();
  334. if (operation == null) continue;
  335. foreach (OperationMessage omsg in operation.Messages)
  336. {
  337. Message msg = ServiceDescriptions.GetMessage (omsg.Message);
  338. if (msg == null) continue;
  339. if (omsg is OperationInput)
  340. inputMessage = msg;
  341. else
  342. outputMessage = msg;
  343. }
  344. if (GetMessageEncoding (oper.Input) == SoapBindingUse.Encoded)
  345. AddMessageSchema (soapSchemas, oper.Input, inputMessage);
  346. else
  347. AddMessageSchema (xmlSchemas, oper.Input, inputMessage);
  348. if (oper.Output != null) {
  349. if (GetMessageEncoding (oper.Output) == SoapBindingUse.Encoded)
  350. AddMessageSchema (soapSchemas, oper.Output, outputMessage);
  351. else
  352. AddMessageSchema (xmlSchemas, oper.Output, outputMessage);
  353. }
  354. }
  355. }
  356. }
  357. }
  358. XmlSchemas defaultList = xmlSchemas;
  359. if (xmlSchemas.Count == 0 && soapSchemas.Count > 0)
  360. defaultList = soapSchemas;
  361. // Schemas not referenced by any message
  362. foreach (XmlSchema sc in Schemas)
  363. {
  364. if (!soapSchemas.Contains (sc) && !xmlSchemas.Contains (sc)) {
  365. if (ImportsEncodedNamespace (sc))
  366. soapSchemas.Add (sc);
  367. else
  368. defaultList.Add (sc);
  369. }
  370. }
  371. }
  372. void AddMessageSchema (XmlSchemas schemas, MessageBinding mb, Message msg)
  373. {
  374. foreach (MessagePart part in msg.Parts)
  375. {
  376. if (part.Element != XmlQualifiedName.Empty)
  377. AddIncludingSchema (schemas, part.Element.Namespace);
  378. else if (part.Type != XmlQualifiedName.Empty)
  379. AddIncludingSchema (schemas, part.Type.Namespace);
  380. }
  381. SoapBodyBinding sbb = mb.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
  382. if (sbb != null) AddIncludingSchema (schemas, sbb.Namespace);
  383. }
  384. void AddIncludingSchema (XmlSchemas list, string ns)
  385. {
  386. XmlSchema sc = Schemas [ns];
  387. if (sc == null || list.Contains (sc)) return;
  388. list.Add (sc);
  389. foreach (XmlSchemaObject ob in sc.Includes)
  390. {
  391. XmlSchemaImport import = ob as XmlSchemaImport;
  392. if (import != null) AddIncludingSchema (list, import.Namespace);
  393. }
  394. }
  395. SoapBindingUse GetMessageEncoding (MessageBinding mb)
  396. {
  397. SoapBodyBinding sbb = mb.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
  398. if (sbb == null)
  399. {
  400. if (mb is InputBinding) return SoapBindingUse.Encoded;
  401. else return SoapBindingUse.Literal;
  402. }
  403. else
  404. if (sbb.Use == SoapBindingUse.Encoded) return SoapBindingUse.Encoded;
  405. else
  406. return SoapBindingUse.Literal;
  407. }
  408. bool ImportsEncodedNamespace (XmlSchema sc)
  409. {
  410. foreach (XmlSchemaObject ob in sc.Includes)
  411. {
  412. XmlSchemaImport import = ob as XmlSchemaImport;
  413. if (import.Namespace == SoapProtocolReflector.EncodingNamespace) return true;
  414. }
  415. return false;
  416. }
  417. #if NET_2_0
  418. void AddAsyncTypes ()
  419. {
  420. foreach (CodeTypeDeclaration type in asyncTypes)
  421. codeNamespace.Types.Add (type);
  422. asyncTypes.Clear ();
  423. }
  424. void AddAsyncMembers (string messageName, CodeMemberMethod method)
  425. {
  426. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  427. CodePrimitiveExpression enull = new CodePrimitiveExpression (null);
  428. CodeMemberField codeField = new CodeMemberField (typeof(System.Threading.SendOrPostCallback), messageName + "OperationCompleted");
  429. codeField.Attributes = MemberAttributes.Private;
  430. CodeTypeDeclaration.Members.Add (codeField);
  431. // Event arguments class
  432. string argsClassName = classNames.AddUnique (messageName + "CompletedEventArgs", null);
  433. CodeTypeDeclaration argsClass = new CodeTypeDeclaration (argsClassName);
  434. argsClass.BaseTypes.Add (new CodeTypeReference ("System.ComponentModel.AsyncCompletedEventArgs"));
  435. CodeMemberField resultsField = new CodeMemberField (typeof(object[]), "results");
  436. resultsField.Attributes = MemberAttributes.Private;
  437. argsClass.Members.Add (resultsField);
  438. CodeConstructor cc = new CodeConstructor ();
  439. cc.Attributes = MemberAttributes.Assembly;
  440. cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object[]), "results"));
  441. cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(System.Exception), "exception"));
  442. cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(bool), "cancelled"));
  443. cc.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "userState"));
  444. cc.BaseConstructorArgs.Add (new CodeVariableReferenceExpression ("exception"));
  445. cc.BaseConstructorArgs.Add (new CodeVariableReferenceExpression ("cancelled"));
  446. cc.BaseConstructorArgs.Add (new CodeVariableReferenceExpression ("userState"));
  447. CodeExpression thisResults = new CodeFieldReferenceExpression (ethis, "results");
  448. cc.Statements.Add (new CodeAssignStatement (thisResults, new CodeVariableReferenceExpression ("results")));
  449. argsClass.Members.Add (cc);
  450. int ind = 0;
  451. if (method.ReturnType.BaseType != "System.Void")
  452. argsClass.Members.Add (CreateArgsProperty (method.ReturnType, "Result", ind++));
  453. foreach (CodeParameterDeclarationExpression par in method.Parameters)
  454. {
  455. if (par.Direction == FieldDirection.Out || par.Direction == FieldDirection.Ref)
  456. argsClass.Members.Add (CreateArgsProperty (par.Type, par.Name, ind++));
  457. }
  458. bool needsArgsClass = (ind > 0);
  459. if (needsArgsClass)
  460. asyncTypes.Add (argsClass);
  461. else
  462. argsClassName = "System.ComponentModel.AsyncCompletedEventArgs";
  463. // Event delegate type
  464. CodeTypeDelegate delegateType = new CodeTypeDelegate (messageName + "CompletedEventHandler");
  465. delegateType.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "sender"));
  466. delegateType.Parameters.Add (new CodeParameterDeclarationExpression (argsClassName, "args"));
  467. // Event member
  468. CodeMemberEvent codeEvent = new CodeMemberEvent ();
  469. codeEvent.Name = messageName + "Completed";
  470. codeEvent.Type = new CodeTypeReference (delegateType.Name);
  471. CodeTypeDeclaration.Members.Add (codeEvent);
  472. // Async method (without user state param)
  473. CodeMemberMethod am = new CodeMemberMethod ();
  474. am.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  475. am.Name = method.Name + "Async";
  476. am.ReturnType = new CodeTypeReference (typeof(void));
  477. CodeMethodInvokeExpression inv;
  478. inv = new CodeMethodInvokeExpression (ethis, am.Name);
  479. am.Statements.Add (inv);
  480. // On...Completed method
  481. CodeMemberMethod onCompleted = new CodeMemberMethod ();
  482. onCompleted.Name = "On" + messageName + "Completed";
  483. onCompleted.Attributes = MemberAttributes.Private | MemberAttributes.Final;
  484. onCompleted.ReturnType = new CodeTypeReference (typeof(void));
  485. onCompleted.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "arg"));
  486. CodeConditionStatement anIf = new CodeConditionStatement ();
  487. CodeExpression eventField = new CodeEventReferenceExpression (ethis, codeEvent.Name);
  488. anIf.Condition = new CodeBinaryOperatorExpression (eventField, CodeBinaryOperatorType.IdentityInequality, enull);
  489. CodeExpression castedArg = new CodeCastExpression (typeof(System.Web.Services.Protocols.InvokeCompletedEventArgs), new CodeVariableReferenceExpression ("arg"));
  490. CodeStatement invokeArgs = new CodeVariableDeclarationStatement (typeof(System.Web.Services.Protocols.InvokeCompletedEventArgs), "invokeArgs", castedArg);
  491. anIf.TrueStatements.Add (invokeArgs);
  492. CodeDelegateInvokeExpression delegateInvoke = new CodeDelegateInvokeExpression ();
  493. delegateInvoke.TargetObject = eventField;
  494. delegateInvoke.Parameters.Add (ethis);
  495. CodeObjectCreateExpression argsInstance = new CodeObjectCreateExpression (argsClassName);
  496. CodeExpression invokeArgsVar = new CodeVariableReferenceExpression ("invokeArgs");
  497. if (needsArgsClass) argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "Results"));
  498. argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "Error"));
  499. argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "Cancelled"));
  500. argsInstance.Parameters.Add (new CodeFieldReferenceExpression (invokeArgsVar, "UserState"));
  501. delegateInvoke.Parameters.Add (argsInstance);
  502. anIf.TrueStatements.Add (delegateInvoke);
  503. onCompleted.Statements.Add (anIf);
  504. // Async method
  505. CodeMemberMethod asyncMethod = new CodeMemberMethod ();
  506. asyncMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  507. asyncMethod.Name = method.Name + "Async";
  508. asyncMethod.ReturnType = new CodeTypeReference (typeof(void));
  509. CodeExpression delegateField = new CodeFieldReferenceExpression (ethis, codeField.Name);
  510. anIf = new CodeConditionStatement ();
  511. anIf.Condition = new CodeBinaryOperatorExpression (delegateField, CodeBinaryOperatorType.IdentityEquality, enull);;
  512. CodeExpression delegateRef = new CodeMethodReferenceExpression (ethis, onCompleted.Name);
  513. CodeExpression newDelegate = new CodeObjectCreateExpression (typeof(System.Threading.SendOrPostCallback), delegateRef);
  514. CodeAssignStatement cas = new CodeAssignStatement (delegateField, newDelegate);
  515. anIf.TrueStatements.Add (cas);
  516. asyncMethod.Statements.Add (anIf);
  517. CodeArrayCreateExpression paramsArray = new CodeArrayCreateExpression (typeof(object));
  518. // Assign parameters
  519. CodeIdentifiers paramsIds = new CodeIdentifiers ();
  520. foreach (CodeParameterDeclarationExpression par in method.Parameters)
  521. {
  522. paramsIds.Add (par.Name, null);
  523. if (par.Direction == FieldDirection.In || par.Direction == FieldDirection.Ref) {
  524. CodeParameterDeclarationExpression inpar = new CodeParameterDeclarationExpression (par.Type, par.Name);
  525. am.Parameters.Add (inpar);
  526. asyncMethod.Parameters.Add (inpar);
  527. inv.Parameters.Add (new CodeVariableReferenceExpression (par.Name));
  528. paramsArray.Initializers.Add (new CodeVariableReferenceExpression (par.Name));
  529. }
  530. }
  531. inv.Parameters.Add (enull);
  532. string userStateName = paramsIds.AddUnique ("userState", null);
  533. asyncMethod.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), userStateName));
  534. CodeExpression userStateVar = new CodeVariableReferenceExpression (userStateName);
  535. asyncMethod.Statements.Add (BuildInvokeAsync (messageName, paramsArray, delegateField, userStateVar));
  536. CodeTypeDeclaration.Members.Add (am);
  537. CodeTypeDeclaration.Members.Add (asyncMethod);
  538. CodeTypeDeclaration.Members.Add (onCompleted);
  539. asyncTypes.Add (delegateType);
  540. }
  541. CodeMemberProperty CreateArgsProperty (CodeTypeReference type, string name, int ind)
  542. {
  543. CodeMemberProperty prop = new CodeMemberProperty ();
  544. prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  545. prop.HasGet = true;
  546. prop.HasSet = false;
  547. prop.Name = name;
  548. prop.Type = type;
  549. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  550. CodeExpression thisResults = new CodeFieldReferenceExpression (ethis, "results");
  551. prop.GetStatements.Add (new CodeMethodInvokeExpression (ethis, "RaiseExceptionIfNecessary"));
  552. CodeArrayIndexerExpression arrValue = new CodeArrayIndexerExpression (thisResults, new CodePrimitiveExpression (ind));
  553. CodeExpression retval = new CodeCastExpression (type, arrValue);
  554. prop.GetStatements.Add (new CodeMethodReturnStatement (retval));
  555. return prop;
  556. }
  557. internal virtual CodeExpression BuildInvokeAsync (string messageName, CodeArrayCreateExpression paramsArray, CodeExpression delegateField, CodeExpression userStateVar)
  558. {
  559. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  560. CodeMethodInvokeExpression inv2 = new CodeMethodInvokeExpression (ethis, "InvokeAsync");
  561. inv2.Parameters.Add (new CodePrimitiveExpression (messageName));
  562. inv2.Parameters.Add (paramsArray);
  563. inv2.Parameters.Add (delegateField);
  564. inv2.Parameters.Add (userStateVar);
  565. return inv2;
  566. }
  567. #endif
  568. [MonoTODO]
  569. public void AddExtensionWarningComments (CodeCommentStatementCollection comments, ServiceDescriptionFormatExtensionCollection extensions)
  570. {
  571. throw new NotImplementedException ();
  572. }
  573. protected abstract CodeTypeDeclaration BeginClass ();
  574. protected virtual void BeginNamespace ()
  575. {
  576. }
  577. protected virtual void EndClass ()
  578. {
  579. }
  580. protected virtual void EndNamespace ()
  581. {
  582. }
  583. protected abstract CodeMemberMethod GenerateMethod ();
  584. protected abstract bool IsBindingSupported ();
  585. protected abstract bool IsOperationFlowSupported (OperationFlow flow);
  586. [MonoTODO]
  587. public Exception OperationBindingSyntaxException (string text)
  588. {
  589. throw new NotImplementedException ();
  590. }
  591. [MonoTODO]
  592. public Exception OperationSyntaxException (string text)
  593. {
  594. throw new NotImplementedException ();
  595. }
  596. public void UnsupportedBindingWarning (string text)
  597. {
  598. warnings |= ServiceDescriptionImportWarnings.UnsupportedBindingsIgnored;
  599. AddGlobalComments ("WARNING: Could not generate proxy for binding " + binding.Name + ". " + text);
  600. }
  601. public void UnsupportedOperationBindingWarning (string text)
  602. {
  603. warnings |= ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored;
  604. AddGlobalComments ("WARNING: Could not generate operation " + OperationBinding.Name + ". " + text);
  605. }
  606. public void UnsupportedOperationWarning (string text)
  607. {
  608. warnings |= ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored;
  609. AddGlobalComments ("WARNING: Could not generate operation " + OperationBinding.Name + ". " + text);
  610. }
  611. void AddGlobalComments (string comments)
  612. {
  613. codeNamespace.Comments.Add (new CodeCommentStatement (comments, false));
  614. }
  615. void AddComments (CodeTypeMember member, string comments)
  616. {
  617. if (comments == null || comments == "") member.Comments.Add (new CodeCommentStatement ("<remarks/>", true));
  618. else member.Comments.Add (new CodeCommentStatement ("<remarks>\n" + comments + "\n</remarks>", true));
  619. }
  620. void AddCodeType (CodeTypeDeclaration type, string comments)
  621. {
  622. AddComments (type, comments);
  623. codeNamespace.Types.Add (type);
  624. }
  625. internal void AddCustomAttribute (CodeTypeMember ctm, CodeAttributeDeclaration att, bool addIfNoParams)
  626. {
  627. if (att.Arguments.Count == 0 && !addIfNoParams) return;
  628. if (ctm.CustomAttributes == null) ctm.CustomAttributes = new CodeAttributeDeclarationCollection ();
  629. ctm.CustomAttributes.Add (att);
  630. }
  631. internal void AddCustomAttribute (CodeTypeMember ctm, string name, params CodeAttributeArgument[] args)
  632. {
  633. if (ctm.CustomAttributes == null) ctm.CustomAttributes = new CodeAttributeDeclarationCollection ();
  634. ctm.CustomAttributes.Add (new CodeAttributeDeclaration (name, args));
  635. }
  636. internal CodeAttributeArgument GetArg (string name, object value)
  637. {
  638. return new CodeAttributeArgument (name, new CodePrimitiveExpression(value));
  639. }
  640. internal CodeAttributeArgument GetEnumArg (string name, string enumType, string enumValue)
  641. {
  642. return new CodeAttributeArgument (name, new CodeFieldReferenceExpression (new CodeTypeReferenceExpression(enumType), enumValue));
  643. }
  644. internal CodeAttributeArgument GetArg (object value)
  645. {
  646. return new CodeAttributeArgument (new CodePrimitiveExpression(value));
  647. }
  648. internal CodeAttributeArgument GetTypeArg (string name, string typeName)
  649. {
  650. return new CodeAttributeArgument (name, new CodeTypeOfExpression(typeName));
  651. }
  652. #endregion
  653. }
  654. }