ServiceContractGenerator.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. //
  2. // ServiceContractGenerator.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // Copyright (C) 2005 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.CodeDom;
  30. using System.Collections.Generic;
  31. using System.Collections.ObjectModel;
  32. using System.Configuration;
  33. using System.Reflection;
  34. using System.Runtime.Serialization;
  35. using System.ServiceModel;
  36. using System.ServiceModel.Channels;
  37. using System.ServiceModel.Configuration;
  38. using System.Xml.Schema;
  39. using System.Xml.Serialization;
  40. using ConfigurationType = System.Configuration.Configuration;
  41. using QName = System.Xml.XmlQualifiedName;
  42. using OPair = System.Collections.Generic.KeyValuePair<System.ServiceModel.Description.IOperationContractGenerationExtension,System.ServiceModel.Description.OperationContractGenerationContext>;
  43. namespace System.ServiceModel.Description
  44. {
  45. public class ServiceContractGenerator
  46. {
  47. CodeCompileUnit ccu;
  48. ConfigurationType config;
  49. Collection<MetadataConversionError> errors
  50. = new Collection<MetadataConversionError> ();
  51. Dictionary<string,string> nsmappings
  52. = new Dictionary<string,string> ();
  53. Dictionary<ContractDescription,Type> referenced_types
  54. = new Dictionary<ContractDescription,Type> ();
  55. ServiceContractGenerationOptions options;
  56. Dictionary<QName, QName> imported_names = null;
  57. ServiceContractGenerationContext contract_context;
  58. List<OPair> operation_contexts = new List<OPair> ();
  59. public ServiceContractGenerator ()
  60. : this (null, null)
  61. {
  62. }
  63. public ServiceContractGenerator (CodeCompileUnit ccu)
  64. : this (ccu, null)
  65. {
  66. }
  67. public ServiceContractGenerator (ConfigurationType config)
  68. : this (null, config)
  69. {
  70. }
  71. public ServiceContractGenerator (CodeCompileUnit ccu, ConfigurationType config)
  72. {
  73. if (ccu == null)
  74. this.ccu = new CodeCompileUnit ();
  75. else
  76. this.ccu = ccu;
  77. this.config = config;
  78. Options |= ServiceContractGenerationOptions.ChannelInterface |
  79. ServiceContractGenerationOptions.ClientClass;
  80. }
  81. public ConfigurationType Configuration {
  82. get { return config; }
  83. }
  84. public Collection<MetadataConversionError> Errors {
  85. get { return errors; }
  86. }
  87. public Dictionary<string,string> NamespaceMappings {
  88. get { return nsmappings; }
  89. }
  90. public ServiceContractGenerationOptions Options {
  91. get { return options; }
  92. set { options = value; }
  93. }
  94. bool GenerateAsync {
  95. get { return (options & ServiceContractGenerationOptions.AsynchronousMethods) != 0; }
  96. }
  97. public Dictionary<ContractDescription,Type> ReferencedTypes {
  98. get { return referenced_types; }
  99. }
  100. public CodeCompileUnit TargetCompileUnit {
  101. get { return ccu; }
  102. }
  103. [MonoTODO]
  104. public void GenerateBinding (Binding binding,
  105. out string bindingSectionName,
  106. out string configurationName)
  107. {
  108. throw new NotImplementedException ();
  109. }
  110. #region Service Contract Type
  111. // Those implementation classes are very likely to be split
  112. // into different classes.
  113. [MonoTODO]
  114. public CodeTypeReference GenerateServiceContractType (
  115. ContractDescription contractDescription)
  116. {
  117. CodeNamespace cns = GetNamespace (contractDescription.Namespace);
  118. imported_names = new Dictionary<QName, QName> ();
  119. var ret = ExportInterface (contractDescription, cns);
  120. // FIXME: handle duplex callback
  121. if ((Options & ServiceContractGenerationOptions.ChannelInterface) != 0)
  122. GenerateChannelInterface (contractDescription, cns);
  123. if ((Options & ServiceContractGenerationOptions.ClientClass) != 0)
  124. GenerateProxyClass (contractDescription, cns);
  125. // Process extensions. Class first, then methods.
  126. // (built-in ones must present before processing class extensions).
  127. foreach (var cb in contractDescription.Behaviors) {
  128. var gex = cb as IServiceContractGenerationExtension;
  129. if (gex != null)
  130. gex.GenerateContract (contract_context);
  131. }
  132. foreach (var opair in operation_contexts)
  133. opair.Key.GenerateOperation (opair.Value);
  134. return ret;
  135. }
  136. CodeNamespace GetNamespace (string ns)
  137. {
  138. if (ns == null)
  139. ns = String.Empty;
  140. foreach (CodeNamespace cns in ccu.Namespaces)
  141. if (cns.Name == ns)
  142. return cns;
  143. CodeNamespace ncns = new CodeNamespace ();
  144. //ncns.Name = ns;
  145. ccu.Namespaces.Add (ncns);
  146. return ncns;
  147. }
  148. CodeTypeDeclaration GetTypeDeclaration (CodeNamespace cns, string name)
  149. {
  150. foreach (CodeTypeDeclaration type in cns.Types)
  151. if (type.Name == name)
  152. return type;
  153. return null;
  154. }
  155. void GenerateProxyClass (ContractDescription cd, CodeNamespace cns)
  156. {
  157. string name = cd.Name + "Client";
  158. if (name [0] == 'I')
  159. name = name.Substring (1);
  160. CodeTypeDeclaration type = GetTypeDeclaration (cns, name);
  161. if (type != null)
  162. return; // already imported
  163. CodeTypeReference clientBase = new CodeTypeReference (typeof (ClientBase<>));
  164. clientBase.TypeArguments.Add (new CodeTypeReference (cd.Name));
  165. type = new CodeTypeDeclaration (name);
  166. cns.Types.Add (type);
  167. type.TypeAttributes = TypeAttributes.Public;
  168. type.BaseTypes.Add (clientBase);
  169. type.BaseTypes.Add (new CodeTypeReference (cd.Name));
  170. // .ctor()
  171. CodeConstructor ctor = new CodeConstructor ();
  172. ctor.Attributes = MemberAttributes.Public;
  173. type.Members.Add (ctor);
  174. // .ctor(string endpointConfigurationName)
  175. ctor = new CodeConstructor ();
  176. ctor.Attributes = MemberAttributes.Public;
  177. ctor.Parameters.Add (
  178. new CodeParameterDeclarationExpression (
  179. new CodeTypeReference (typeof (string)), "endpointConfigurationName"));
  180. ctor.BaseConstructorArgs.Add (
  181. new CodeArgumentReferenceExpression ("endpointConfigurationName"));
  182. type.Members.Add (ctor);
  183. // .ctor(string endpointConfigurationName, string remoteAddress)
  184. ctor = new CodeConstructor ();
  185. ctor.Attributes = MemberAttributes.Public;
  186. ctor.Parameters.Add (
  187. new CodeParameterDeclarationExpression (
  188. new CodeTypeReference (typeof (string)), "endpointConfigurationName"));
  189. ctor.Parameters.Add (
  190. new CodeParameterDeclarationExpression (
  191. new CodeTypeReference (typeof (string)), "remoteAddress"));
  192. ctor.BaseConstructorArgs.Add (
  193. new CodeArgumentReferenceExpression ("endpointConfigurationName"));
  194. ctor.BaseConstructorArgs.Add (
  195. new CodeArgumentReferenceExpression ("remoteAddress"));
  196. type.Members.Add (ctor);
  197. // .ctor(string endpointConfigurationName, EndpointAddress remoteAddress)
  198. ctor = new CodeConstructor ();
  199. ctor.Attributes = MemberAttributes.Public;
  200. ctor.Parameters.Add (
  201. new CodeParameterDeclarationExpression (
  202. new CodeTypeReference (typeof (string)), "endpointConfigurationName"));
  203. ctor.Parameters.Add (
  204. new CodeParameterDeclarationExpression (
  205. new CodeTypeReference (typeof (EndpointAddress)), "remoteAddress"));
  206. ctor.BaseConstructorArgs.Add (
  207. new CodeArgumentReferenceExpression ("endpointConfigurationName"));
  208. ctor.BaseConstructorArgs.Add (
  209. new CodeArgumentReferenceExpression ("remoteAddress"));
  210. type.Members.Add (ctor);
  211. // .ctor(Binding,EndpointAddress)
  212. ctor = new CodeConstructor ();
  213. ctor.Attributes = MemberAttributes.Public;
  214. ctor.Parameters.Add (
  215. new CodeParameterDeclarationExpression (
  216. new CodeTypeReference (typeof (Binding)), "binding"));
  217. ctor.Parameters.Add (
  218. new CodeParameterDeclarationExpression (
  219. new CodeTypeReference (typeof (EndpointAddress)), "endpoint"));
  220. ctor.BaseConstructorArgs.Add (
  221. new CodeArgumentReferenceExpression ("binding"));
  222. ctor.BaseConstructorArgs.Add (
  223. new CodeArgumentReferenceExpression ("endpoint"));
  224. type.Members.Add (ctor);
  225. // service contract methods
  226. AddImplementationClientMethods (type, cd);
  227. }
  228. void GenerateChannelInterface (ContractDescription cd, CodeNamespace cns)
  229. {
  230. string name = cd.Name + "Channel";
  231. CodeTypeDeclaration type = GetTypeDeclaration (cns, name);
  232. if (type != null)
  233. return;
  234. type = new CodeTypeDeclaration ();
  235. type.Name = name;
  236. type.TypeAttributes = TypeAttributes.Interface | TypeAttributes.Public;
  237. cns.Types.Add (type);
  238. type.BaseTypes.Add (ExportInterface (cd, cns));
  239. type.BaseTypes.Add (new CodeTypeReference (typeof (System.ServiceModel.IClientChannel)));
  240. }
  241. CodeTypeReference ExportInterface (ContractDescription cd, CodeNamespace cns)
  242. {
  243. CodeTypeDeclaration type = GetTypeDeclaration (cns, cd.Name);
  244. if (type != null)
  245. return new CodeTypeReference (type.Name);
  246. type = new CodeTypeDeclaration ();
  247. type.TypeAttributes = TypeAttributes.Interface;
  248. type.TypeAttributes |= TypeAttributes.Public;
  249. cns.Types.Add (type);
  250. type.Name = cd.Name;
  251. CodeAttributeDeclaration ad =
  252. new CodeAttributeDeclaration (
  253. new CodeTypeReference (
  254. typeof (ServiceContractAttribute)));
  255. ad.Arguments.Add (new CodeAttributeArgument ("Namespace", new CodePrimitiveExpression (cd.Namespace)));
  256. type.CustomAttributes.Add (ad);
  257. contract_context = new ServiceContractGenerationContext (this, cd, type);
  258. AddOperationMethods (type, cd);
  259. return new CodeTypeReference (type.Name);
  260. }
  261. void AddBeginAsyncArgs (CodeMemberMethod cm)
  262. {
  263. var acb = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (AsyncCallback)), "asyncCallback");
  264. cm.Parameters.Add (acb);
  265. var us = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (object)), "userState");
  266. cm.Parameters.Add (us);
  267. }
  268. void AddOperationMethods (CodeTypeDeclaration type, ContractDescription cd)
  269. {
  270. foreach (OperationDescription od in cd.Operations) {
  271. CodeMemberMethod syncMethod = null, beginMethod = null, endMethod = null;
  272. CodeMemberMethod cm = new CodeMemberMethod ();
  273. type.Members.Add (cm);
  274. if (GenerateAsync) {
  275. cm.Name = "Begin" + od.Name;
  276. beginMethod = cm;
  277. } else {
  278. cm.Name = od.Name;
  279. syncMethod = cm;
  280. }
  281. CodeTypeReference returnTypeFromMessageContract = null;
  282. if (od.SyncMethod != null) {
  283. ExportParameters (cm, od.SyncMethod.GetParameters ());
  284. if (GenerateAsync) {
  285. AddBeginAsyncArgs (cm);
  286. cm.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
  287. }
  288. else
  289. cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType);
  290. } else {
  291. ExportMessages (od.Messages, cm, false);
  292. returnTypeFromMessageContract = cm.ReturnType;
  293. if (GenerateAsync) {
  294. AddBeginAsyncArgs (cm);
  295. cm.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
  296. }
  297. }
  298. // [OperationContract (Action = "...", ReplyAction = "..")]
  299. CodeAttributeDeclaration ad =
  300. new CodeAttributeDeclaration (
  301. new CodeTypeReference (
  302. typeof (OperationContractAttribute)));
  303. foreach (MessageDescription md in od.Messages) {
  304. if (md.Direction == MessageDirection.Input)
  305. ad.Arguments.Add (new CodeAttributeArgument ("Action", new CodePrimitiveExpression (md.Action)));
  306. else
  307. ad.Arguments.Add (new CodeAttributeArgument ("ReplyAction", new CodePrimitiveExpression (md.Action)));
  308. }
  309. if (GenerateAsync)
  310. ad.Arguments.Add (new CodeAttributeArgument ("AsyncPattern", new CodePrimitiveExpression (true)));
  311. cm.CustomAttributes.Add (ad);
  312. // For async mode, add EndXxx() too.
  313. if (GenerateAsync) {
  314. cm = new CodeMemberMethod ();
  315. type.Members.Add (cm);
  316. cm.Name = "End" + od.Name;
  317. endMethod = cm;
  318. var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result");
  319. cm.Parameters.Add (res);
  320. if (od.SyncMethod != null) // FIXME: it depends on sync method!
  321. cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType);
  322. else
  323. cm.ReturnType = returnTypeFromMessageContract;
  324. }
  325. foreach (var ob in od.Behaviors) {
  326. var gex = ob as IOperationContractGenerationExtension;
  327. if (gex != null)
  328. operation_contexts.Add (new OPair (gex, new OperationContractGenerationContext (this, contract_context, od, type, syncMethod, beginMethod, endMethod)));
  329. }
  330. }
  331. }
  332. void ExportParameters (CodeMemberMethod method, ParameterInfo [] parameters)
  333. {
  334. foreach (ParameterInfo pi in parameters)
  335. method.Parameters.Add (
  336. new CodeParameterDeclarationExpression (
  337. new CodeTypeReference (pi.ParameterType),
  338. pi.Name));
  339. }
  340. void AddImplementationClientMethods (CodeTypeDeclaration type, ContractDescription cd)
  341. {
  342. foreach (OperationDescription od in cd.Operations) {
  343. CodeMemberMethod cm = new CodeMemberMethod ();
  344. type.Members.Add (cm);
  345. if (GenerateAsync)
  346. cm.Name = "Begin" + od.Name;
  347. else
  348. cm.Name = od.Name;
  349. cm.Attributes = MemberAttributes.Public
  350. | MemberAttributes.Final;
  351. CodeTypeReference returnTypeFromMessageContract = null;
  352. List<CodeExpression> args = new List<CodeExpression> ();
  353. if (od.SyncMethod != null) {
  354. ParameterInfo [] pars = od.SyncMethod.GetParameters ();
  355. ExportParameters (cm, pars);
  356. cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType);
  357. int i = 0;
  358. foreach (ParameterInfo pi in pars)
  359. args.Add (new CodeArgumentReferenceExpression (pi.Name));
  360. } else {
  361. args.AddRange (ExportMessages (od.Messages, cm, true));
  362. returnTypeFromMessageContract = cm.ReturnType;
  363. if (GenerateAsync) {
  364. AddBeginAsyncArgs (cm);
  365. cm.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
  366. }
  367. }
  368. if (GenerateAsync) {
  369. args.Add (new CodeArgumentReferenceExpression ("asyncCallback"));
  370. args.Add (new CodeArgumentReferenceExpression ("userState"));
  371. }
  372. CodeExpression call = new CodeMethodInvokeExpression (
  373. new CodePropertyReferenceExpression (
  374. new CodeBaseReferenceExpression (),
  375. "Channel"),
  376. cm.Name,
  377. args.ToArray ());
  378. if (cm.ReturnType.BaseType == "System.Void")
  379. cm.Statements.Add (new CodeExpressionStatement (call));
  380. else
  381. cm.Statements.Add (new CodeMethodReturnStatement (call));
  382. // For async mode, add EndXxx() too.
  383. if (!GenerateAsync)
  384. return;
  385. // EndXxx() implementation
  386. cm = new CodeMemberMethod ();
  387. cm.Attributes = MemberAttributes.Public
  388. | MemberAttributes.Final;
  389. type.Members.Add (cm);
  390. cm.Name = "End" + od.Name;
  391. var res = new CodeParameterDeclarationExpression (new CodeTypeReference (typeof (IAsyncResult)), "result");
  392. cm.Parameters.Add (res);
  393. if (od.SyncMethod != null) // FIXME: it depends on sync method!
  394. cm.ReturnType = new CodeTypeReference (od.SyncMethod.ReturnType);
  395. else
  396. cm.ReturnType = returnTypeFromMessageContract;
  397. string resultArgName = "result";
  398. if (od.EndMethod != null)
  399. resultArgName = od.EndMethod.GetParameters () [0].Name;
  400. call = new CodeMethodInvokeExpression (
  401. new CodePropertyReferenceExpression (
  402. new CodeBaseReferenceExpression (),
  403. "Channel"),
  404. cm.Name,
  405. new CodeArgumentReferenceExpression (resultArgName));
  406. if (cm.ReturnType.BaseType == "System.Void")
  407. cm.Statements.Add (new CodeExpressionStatement (call));
  408. else
  409. cm.Statements.Add (new CodeMethodReturnStatement (call));
  410. }
  411. }
  412. private CodeExpression[] ExportMessages (MessageDescriptionCollection messages, CodeMemberMethod method, bool return_args)
  413. {
  414. CodeExpression [] args = null;
  415. foreach (MessageDescription md in messages) {
  416. if (md.Direction == MessageDirection.Output) {
  417. if (md.Body.ReturnValue != null) {
  418. ExportDataContract (md.Body.ReturnValue.XmlTypeMapping);
  419. method.ReturnType = new CodeTypeReference (md.Body.ReturnValue.TypeName.Name);
  420. }
  421. continue;
  422. }
  423. if (return_args)
  424. args = new CodeExpression [md.Body.Parts.Count];
  425. MessagePartDescriptionCollection parts = md.Body.Parts;
  426. for (int i = 0; i < parts.Count; i++) {
  427. ExportDataContract (parts [i].XmlTypeMapping);
  428. method.Parameters.Add (
  429. new CodeParameterDeclarationExpression (
  430. new CodeTypeReference (parts [i].TypeName.Name),
  431. parts [i].Name));
  432. if (return_args)
  433. args [i] = new CodeArgumentReferenceExpression (parts [i].Name);
  434. }
  435. }
  436. return args;
  437. }
  438. #endregion
  439. [MonoTODO]
  440. public CodeTypeReference GenerateServiceEndpoint (
  441. ServiceEndpoint endpoint,
  442. out ChannelEndpointElement channelElement)
  443. {
  444. throw new NotImplementedException ();
  445. }
  446. private void ExportDataContract (XmlTypeMapping mapping)
  447. {
  448. if (mapping == null)
  449. return;
  450. QName qname = new QName (mapping.TypeName, mapping.Namespace);
  451. if (imported_names.ContainsKey (qname))
  452. return;
  453. CodeNamespace cns = new CodeNamespace ();
  454. XmlCodeExporter xce = new XmlCodeExporter (cns);
  455. xce.ExportTypeMapping (mapping);
  456. List <CodeTypeDeclaration> to_remove = new List <CodeTypeDeclaration> ();
  457. //Process the types just generated
  458. //FIXME: Iterate and assign the types to correct namespaces
  459. //At the end, add all those namespaces to the ccu
  460. foreach (CodeTypeDeclaration type in cns.Types) {
  461. string ns = GetXmlNamespace (type);
  462. if (ns == null)
  463. //FIXME: do what here?
  464. continue;
  465. QName type_name = new QName (type.Name, ns);
  466. if (imported_names.ContainsKey (type_name)) {
  467. //Type got reemitted, so remove it!
  468. to_remove.Add (type);
  469. continue;
  470. }
  471. imported_names [type_name] = type_name;
  472. type.Comments.Clear ();
  473. //Custom Attributes
  474. type.CustomAttributes.Clear ();
  475. if (type.IsEnum)
  476. continue;
  477. type.CustomAttributes.Add (
  478. new CodeAttributeDeclaration (
  479. new CodeTypeReference ("System.CodeDom.Compiler.GeneratedCodeAttribute"),
  480. new CodeAttributeArgument (new CodePrimitiveExpression ("System.Runtime.Serialization")),
  481. new CodeAttributeArgument (new CodePrimitiveExpression ("3.0.0.0"))));
  482. type.CustomAttributes.Add (
  483. new CodeAttributeDeclaration (
  484. new CodeTypeReference ("System.Runtime.Serialization.DataContractAttribute")));
  485. //BaseType and interface
  486. type.BaseTypes.Add (new CodeTypeReference (typeof (object)));
  487. type.BaseTypes.Add (new CodeTypeReference ("System.Runtime.Serialization.IExtensibleDataObject"));
  488. foreach (CodeTypeMember mbr in type.Members) {
  489. CodeMemberProperty p = mbr as CodeMemberProperty;
  490. if (p == null)
  491. continue;
  492. if ((p.Attributes & MemberAttributes.Public) == MemberAttributes.Public) {
  493. //FIXME: Clear all attributes or only XmlElementAttribute?
  494. p.CustomAttributes.Clear ();
  495. p.CustomAttributes.Add (new CodeAttributeDeclaration (
  496. new CodeTypeReference ("System.Runtime.Serialization.DataMemberAttribute")));
  497. p.Comments.Clear ();
  498. }
  499. }
  500. //Fields
  501. CodeMemberField field = new CodeMemberField (
  502. new CodeTypeReference ("System.Runtime.Serialization.ExtensionDataObject"),
  503. "extensionDataField");
  504. field.Attributes = MemberAttributes.Private | MemberAttributes.Final;
  505. type.Members.Add (field);
  506. //Property
  507. CodeMemberProperty prop = new CodeMemberProperty ();
  508. prop.Type = new CodeTypeReference ("System.Runtime.Serialization.ExtensionDataObject");
  509. prop.Name = "ExtensionData";
  510. prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  511. //Get
  512. prop.GetStatements.Add (new CodeMethodReturnStatement (
  513. new CodeFieldReferenceExpression (
  514. new CodeThisReferenceExpression (),
  515. "extensionDataField")));
  516. //Set
  517. prop.SetStatements.Add (new CodeAssignStatement (
  518. new CodeFieldReferenceExpression (
  519. new CodeThisReferenceExpression (),
  520. "extensionDataField"),
  521. new CodePropertySetValueReferenceExpression ()));
  522. type.Members.Add (prop);
  523. }
  524. foreach (CodeTypeDeclaration type in to_remove)
  525. cns.Types.Remove (type);
  526. ccu.Namespaces.Add (cns);
  527. }
  528. private string GetXmlNamespace (CodeTypeDeclaration type)
  529. {
  530. foreach (CodeAttributeDeclaration attr in type.CustomAttributes) {
  531. if (attr.Name == "System.Xml.Serialization.XmlTypeAttribute" ||
  532. attr.Name == "System.Xml.Serialization.XmlRootAttribute") {
  533. foreach (CodeAttributeArgument arg in attr.Arguments)
  534. if (arg.Name == "Namespace")
  535. return ((CodePrimitiveExpression)arg.Value).Value as string;
  536. //Could not find Namespace arg!
  537. return null;
  538. }
  539. }
  540. return null;
  541. }
  542. }
  543. }