MetaDataExporter.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. //
  2. // System.Runtime.Remoting.MetadataServices.MetaDataExporter
  3. //
  4. // Authors:
  5. // Lluis Sanchez Gual ([email protected])
  6. //
  7. // (C) 2003 Novell, Inc
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System.Collections;
  30. using System.IO;
  31. using System.Text;
  32. using System.Xml;
  33. using System.Reflection;
  34. using System.Net;
  35. using System.Runtime.Remoting;
  36. using System.Runtime.Remoting.Metadata;
  37. using System.Runtime.Serialization;
  38. namespace System.Runtime.Remoting.MetadataServices
  39. {
  40. internal class MetaDataExporter
  41. {
  42. public void ExportTypes (ServiceType[] servicetypes, SdlType sdltype, XmlTextWriter tw)
  43. {
  44. if (sdltype == SdlType.Sdl) // Obsolete, we don't support this
  45. throw new NotSupportedException ();
  46. if (servicetypes.Length == 0) return;
  47. Type maint = servicetypes [0].ObjectType;
  48. Hashtable dataTypes = new Hashtable ();
  49. ArrayList services = new ArrayList ();
  50. FindTypes (servicetypes, dataTypes, services);
  51. if (services.Count > 0)
  52. maint = ((ServiceType) services[0]).ObjectType;
  53. string serviceNs = GetXmlNamespace (maint, null);
  54. tw.Formatting = Formatting.Indented;
  55. tw.WriteStartElement ("definitions", MetaData.WsdlNamespace);
  56. tw.WriteAttributeString ("name", maint.Name);
  57. tw.WriteAttributeString ("targetNamespace", serviceNs);
  58. tw.WriteAttributeString ("xmlns", MetaData.XmlnsNamespace, MetaData.WsdlNamespace);
  59. tw.WriteAttributeString ("xmlns", "tns", MetaData.XmlnsNamespace, serviceNs);
  60. tw.WriteAttributeString ("xmlns", "xsd", MetaData.XmlnsNamespace, MetaData.SchemaNamespace);
  61. tw.WriteAttributeString ("xmlns", "xsi", MetaData.XmlnsNamespace, MetaData.SchemaInstanceNamespace);
  62. tw.WriteAttributeString ("xmlns", "suds", MetaData.XmlnsNamespace, MetaData.SudsNamespace);
  63. tw.WriteAttributeString ("xmlns", "wsdl", MetaData.XmlnsNamespace, MetaData.WsdlNamespace);
  64. tw.WriteAttributeString ("xmlns", "soapenc", MetaData.XmlnsNamespace, MetaData.SoapEncodingNamespace);
  65. tw.WriteAttributeString ("xmlns", "soap", MetaData.XmlnsNamespace, MetaData.SoapNamespace);
  66. int nums = 0;
  67. foreach (DictionaryEntry entry in dataTypes)
  68. {
  69. string ns = (string) entry.Key;
  70. if (tw.LookupPrefix (ns) != null) continue;
  71. tw.WriteAttributeString ("xmlns", "ns"+nums, MetaData.XmlnsNamespace, ns);
  72. nums++;
  73. }
  74. // Schema
  75. if (dataTypes.Count > 0)
  76. {
  77. tw.WriteStartElement ("types", MetaData.WsdlNamespace);
  78. foreach (DictionaryEntry entry in dataTypes)
  79. {
  80. SchemaInfo sinfo = (SchemaInfo) entry.Value;
  81. if (sinfo == null || sinfo.Types.Count == 0) continue;
  82. tw.WriteStartElement ("s", "schema", MetaData.SchemaNamespace);
  83. tw.WriteAttributeString ("targetNamespace", (string) entry.Key);
  84. tw.WriteAttributeString ("elementFormDefault", "unqualified");
  85. tw.WriteAttributeString ("attributeFormDefault", "unqualified");
  86. foreach (string ns in sinfo.Imports)
  87. {
  88. if (ns == (string) entry.Key) continue;
  89. tw.WriteStartElement ("import", MetaData.SchemaNamespace);
  90. tw.WriteAttributeString ("namespace", ns);
  91. tw.WriteEndElement ();
  92. }
  93. foreach (Type type in sinfo.Types)
  94. WriteDataTypeSchema (tw, type);
  95. tw.WriteEndElement ();
  96. }
  97. tw.WriteEndElement ();
  98. }
  99. // Bindings
  100. /* foreach (ServiceType st in servicetypes)
  101. WriteServiceBinding (tw, st);
  102. */
  103. foreach (ServiceType st in services)
  104. WriteServiceBinding (tw, st, dataTypes);
  105. // Service element
  106. tw.WriteStartElement ("service", MetaData.WsdlNamespace);
  107. if (services.Count > 0)
  108. tw.WriteAttributeString ("name", GetServiceName (maint));
  109. else
  110. tw.WriteAttributeString ("name", "Service");
  111. foreach (ServiceType st in services)
  112. {
  113. WriteServiceType (tw, st);
  114. }
  115. tw.WriteEndElement ();
  116. // Closing
  117. tw.WriteEndElement ();
  118. tw.Flush ();
  119. }
  120. void WriteServiceType (XmlTextWriter tw, ServiceType st)
  121. {
  122. tw.WriteStartElement ("port", MetaData.WsdlNamespace);
  123. tw.WriteAttributeString ("name", GetPortName (st.ObjectType));
  124. tw.WriteAttributeString ("binding", "tns:" + GetBindingName (st.ObjectType));
  125. if (st.Url != null)
  126. {
  127. tw.WriteStartElement ("soap","address", MetaData.SoapNamespace);
  128. tw.WriteAttributeString ("location", st.Url);
  129. tw.WriteEndElement ();
  130. }
  131. tw.WriteEndElement ();
  132. }
  133. void WriteServiceBinding (XmlTextWriter tw, ServiceType st, Hashtable dataTypes)
  134. {
  135. Type type = st.ObjectType;
  136. string typeName = type.Name;
  137. MethodInfo[] mets = type.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  138. bool isService = IsService (type);
  139. // Messages
  140. if (isService)
  141. {
  142. foreach (MethodInfo met in mets)
  143. {
  144. if (met.DeclaringType.Assembly == typeof(object).Assembly) continue;
  145. ParameterInfo[] pars = met.GetParameters ();
  146. tw.WriteStartElement ("message", MetaData.WsdlNamespace);
  147. tw.WriteAttributeString ("name", typeName + "." + met.Name + "Input");
  148. foreach (ParameterInfo par in pars)
  149. {
  150. if (!par.ParameterType.IsByRef)
  151. WritePart (tw, par.Name, par.ParameterType, type);
  152. }
  153. tw.WriteEndElement (); // message
  154. tw.WriteStartElement ("message", MetaData.WsdlNamespace);
  155. tw.WriteAttributeString ("name", typeName + "." + met.Name + "Output");
  156. if (met.ReturnType != typeof(void))
  157. WritePart (tw, "return", met.ReturnType, type);
  158. foreach (ParameterInfo par in pars)
  159. {
  160. if (par.ParameterType.IsByRef || par.IsOut)
  161. WritePart (tw, par.Name, par.ParameterType, type);
  162. }
  163. tw.WriteEndElement (); // message
  164. }
  165. }
  166. // Port type
  167. tw.WriteStartElement ("portType", MetaData.WsdlNamespace);
  168. tw.WriteAttributeString ("name", typeName + "PortType");
  169. if (isService)
  170. {
  171. foreach (MethodInfo met in mets)
  172. {
  173. if (met.DeclaringType.Assembly == typeof(object).Assembly) continue;
  174. tw.WriteStartElement ("operation", MetaData.WsdlNamespace);
  175. tw.WriteAttributeString ("name", met.Name);
  176. StringBuilder sb = new StringBuilder ();
  177. ParameterInfo[] pars = met.GetParameters ();
  178. foreach (ParameterInfo par in pars)
  179. {
  180. if (sb.Length != 0) sb.Append (" ");
  181. sb.Append (par.Name);
  182. }
  183. tw.WriteAttributeString ("parameterOrder", sb.ToString ());
  184. tw.WriteStartElement ("input", MetaData.WsdlNamespace);
  185. tw.WriteAttributeString ("name", met.Name + "Request");
  186. tw.WriteAttributeString ("message", "tns:" + typeName + "." + met.Name + "Input");
  187. tw.WriteEndElement ();
  188. tw.WriteStartElement ("output", MetaData.WsdlNamespace);
  189. tw.WriteAttributeString ("name", met.Name + "Response");
  190. tw.WriteAttributeString ("message", "tns:" + typeName + "." + met.Name + "Output");
  191. tw.WriteEndElement ();
  192. tw.WriteEndElement (); // operation
  193. }
  194. }
  195. tw.WriteEndElement (); // portType
  196. // Binding
  197. tw.WriteStartElement ("binding", MetaData.WsdlNamespace);
  198. tw.WriteAttributeString ("name", typeName + "Binding");
  199. tw.WriteAttributeString ("type", "tns:" + typeName + "PortType");
  200. tw.WriteStartElement ("soap", "binding", MetaData.SoapNamespace);
  201. tw.WriteAttributeString ("style", "rpc");
  202. tw.WriteAttributeString ("transport", "http://schemas.xmlsoap.org/soap/http");
  203. tw.WriteEndElement ();
  204. WriteTypeSuds (tw, type);
  205. SchemaInfo sinfo = (SchemaInfo) dataTypes [GetXmlNamespace (type,null)];
  206. if (sinfo != null && !sinfo.SudsGenerated)
  207. {
  208. foreach (Type dt in sinfo.Types)
  209. WriteTypeSuds (tw, dt);
  210. sinfo.SudsGenerated = true;
  211. }
  212. if (isService)
  213. {
  214. foreach (MethodInfo met in mets)
  215. {
  216. if (met.DeclaringType.Assembly == typeof(object).Assembly) continue;
  217. tw.WriteStartElement ("operation", MetaData.WsdlNamespace);
  218. tw.WriteAttributeString ("name", met.Name);
  219. tw.WriteStartElement ("soap", "operation", MetaData.SoapNamespace);
  220. tw.WriteAttributeString ("soapAction", GetSoapAction (met));
  221. tw.WriteEndElement ();
  222. tw.WriteStartElement ("suds", "method", MetaData.SudsNamespace);
  223. tw.WriteAttributeString ("attributes", "public");
  224. tw.WriteEndElement ();
  225. tw.WriteStartElement ("input", MetaData.WsdlNamespace);
  226. tw.WriteAttributeString ("name", met.Name + "Request");
  227. WriteMessageBindingBody (tw, type);
  228. tw.WriteEndElement ();
  229. tw.WriteStartElement ("output", MetaData.WsdlNamespace);
  230. tw.WriteAttributeString ("name", met.Name + "Response");
  231. WriteMessageBindingBody (tw, type);
  232. tw.WriteEndElement ();
  233. tw.WriteEndElement (); // operation
  234. }
  235. }
  236. tw.WriteEndElement (); // binding
  237. }
  238. void WriteTypeSuds (XmlTextWriter tw, Type type)
  239. {
  240. if (type.IsArray || type.IsEnum)
  241. {
  242. return;
  243. }
  244. else if (type.IsInterface)
  245. {
  246. tw.WriteStartElement ("suds", "interface", MetaData.SudsNamespace);
  247. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
  248. foreach (Type interf in type.GetInterfaces ()) {
  249. tw.WriteStartElement ("suds","extends", MetaData.SudsNamespace);
  250. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, interf, null));
  251. tw.WriteEndElement ();
  252. }
  253. }
  254. else if (type.IsValueType)
  255. {
  256. tw.WriteStartElement ("suds", "struct", MetaData.SudsNamespace);
  257. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
  258. if (type.BaseType != typeof(ValueType))
  259. tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
  260. }
  261. else
  262. {
  263. tw.WriteStartElement ("suds", "class", MetaData.SudsNamespace);
  264. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
  265. if (IsService (type))
  266. {
  267. if (type.IsMarshalByRef)
  268. tw.WriteAttributeString ("rootType", "MarshalByRefObject");
  269. else
  270. tw.WriteAttributeString ("rootType", "Delegate");
  271. if (type.BaseType != typeof(MarshalByRefObject))
  272. tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
  273. if (type.IsMarshalByRef) {
  274. foreach (Type interf in type.GetInterfaces ()) {
  275. tw.WriteStartElement ("suds","implements", MetaData.SudsNamespace);
  276. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, interf, null));
  277. tw.WriteEndElement ();
  278. }
  279. }
  280. }
  281. else if (typeof(ISerializable).IsAssignableFrom (type))
  282. tw.WriteAttributeString ("rootType", "ISerializable");
  283. }
  284. tw.WriteEndElement (); // suds
  285. }
  286. void WriteMessageBindingBody (XmlTextWriter tw, Type t)
  287. {
  288. tw.WriteStartElement ("soap", "body", MetaData.SoapNamespace);
  289. tw.WriteAttributeString ("use", "encoded");
  290. tw.WriteAttributeString ("encodingStyle", MetaData.SoapEncodingNamespace);
  291. tw.WriteAttributeString ("namespace", GetXmlNamespace (t, null));
  292. tw.WriteEndElement ();
  293. }
  294. void WritePart (XmlTextWriter tw, string name, Type t, Type containerType)
  295. {
  296. tw.WriteStartElement ("part", MetaData.WsdlNamespace);
  297. tw.WriteAttributeString ("name", name);
  298. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, t, containerType));
  299. tw.WriteEndElement ();
  300. }
  301. void WriteDataTypeSchema (XmlTextWriter tw, Type type)
  302. {
  303. if (type.IsArray)
  304. WriteArraySchema (tw, type);
  305. else if (type.IsEnum)
  306. WriteEnumSchema (tw, type);
  307. else
  308. WriteClassSchema (tw, type);
  309. }
  310. void WriteArraySchema (XmlTextWriter tw, Type type)
  311. {
  312. tw.WriteStartElement ("complexType", MetaData.SchemaNamespace);
  313. tw.WriteAttributeString ("name", GetXmlType (type));
  314. tw.WriteStartElement ("complexContent", MetaData.SchemaNamespace);
  315. tw.WriteStartElement ("restriction", MetaData.SchemaNamespace);
  316. tw.WriteAttributeString ("base", GetQualifiedName (tw, MetaData.SoapEncodingNamespace, "Array"));
  317. tw.WriteStartElement ("attribute", MetaData.SchemaNamespace);
  318. tw.WriteAttributeString ("ref", GetQualifiedName (tw, MetaData.SoapEncodingNamespace, "arrayType"));
  319. string arrayType = "";
  320. while (type.IsArray)
  321. {
  322. arrayType = arrayType + "[" + new string (',', type.GetArrayRank()-1) + "]";
  323. type = type.GetElementType ();
  324. }
  325. arrayType = GetQualifiedXmlType (tw, type, null) + arrayType;
  326. tw.WriteAttributeString ("wsdl", "arrayType", MetaData.WsdlNamespace, arrayType);
  327. tw.WriteEndElement (); // attribute
  328. tw.WriteEndElement (); // restriction
  329. tw.WriteEndElement (); // complexContent
  330. tw.WriteEndElement (); // complexType
  331. }
  332. void WriteEnumSchema (XmlTextWriter tw, Type type)
  333. {
  334. tw.WriteStartElement ("simpleType", MetaData.SchemaNamespace);
  335. tw.WriteAttributeString ("name", GetXmlType (type));
  336. tw.WriteAttributeString ("suds", "enumType", MetaData.SudsNamespace, GetQualifiedXmlType (tw, EnumToUnderlying (type), null));
  337. tw.WriteStartElement ("restriction", MetaData.SchemaNamespace);
  338. tw.WriteAttributeString ("base", "xsd:string");
  339. foreach (string name in Enum.GetNames (type))
  340. {
  341. tw.WriteStartElement ("enumeration", MetaData.SchemaNamespace);
  342. tw.WriteAttributeString ("value", name);
  343. tw.WriteEndElement ();
  344. }
  345. tw.WriteEndElement (); // restriction
  346. tw.WriteEndElement (); // simpleType
  347. }
  348. void WriteClassSchema (XmlTextWriter tw, Type type)
  349. {
  350. tw.WriteStartElement ("element", MetaData.SchemaNamespace);
  351. tw.WriteAttributeString ("name", type.Name);
  352. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
  353. tw.WriteEndElement ();
  354. tw.WriteStartElement ("complexType", MetaData.SchemaNamespace);
  355. tw.WriteAttributeString ("name", GetXmlType (type));
  356. if (type.BaseType != null && type.BaseType != typeof(object) && type.BaseType != typeof(ValueType))
  357. tw.WriteAttributeString ("base", GetQualifiedXmlType (tw, type.BaseType, null));
  358. FieldInfo[] fields = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  359. // Element fields
  360. bool elemsStart = false;
  361. foreach (FieldInfo fi in fields)
  362. {
  363. SoapFieldAttribute att = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (fi);
  364. if (att.UseAttribute) continue;
  365. if (!elemsStart) { tw.WriteStartElement ("all", MetaData.SchemaNamespace); elemsStart = true; }
  366. tw.WriteStartElement ("element", MetaData.SchemaNamespace);
  367. tw.WriteAttributeString ("name", att.XmlElementName);
  368. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, fi.FieldType, type));
  369. tw.WriteEndElement ();
  370. }
  371. if (elemsStart) tw.WriteEndElement (); // all
  372. // Attribute fields
  373. foreach (FieldInfo fi in fields)
  374. {
  375. SoapFieldAttribute att = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (fi);
  376. if (!att.UseAttribute) continue;
  377. tw.WriteStartElement ("attribute", MetaData.SchemaNamespace);
  378. tw.WriteAttributeString ("name", att.XmlElementName);
  379. tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, fi.FieldType, type));
  380. tw.WriteEndElement ();
  381. }
  382. tw.WriteEndElement (); // complexType
  383. }
  384. ArrayList FindServices (ServiceType[] servicetypes)
  385. {
  386. ArrayList list = new ArrayList ();
  387. foreach (ServiceType st in servicetypes)
  388. if (IsService (st.ObjectType)) list.Add (st);
  389. return list;
  390. }
  391. string GetSoapAction (MethodInfo mb)
  392. {
  393. return SoapServices.GetSoapActionFromMethodBase (mb);
  394. }
  395. string GetXmlNamespace (Type t, Type containerType)
  396. {
  397. string name, ns;
  398. if (t.IsArray)
  399. {
  400. return GetXmlNamespace (containerType, null);
  401. }
  402. if (SoapServices.GetXmlTypeForInteropType (t, out name, out ns))
  403. return ns;
  404. SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (t);
  405. return att.XmlNamespace;
  406. }
  407. string GetQualifiedName (XmlTextWriter tw, string namspace, string localName)
  408. {
  409. return tw.LookupPrefix (namspace) + ":" + localName;
  410. }
  411. string GetQualifiedXmlType (XmlTextWriter tw, Type type, Type containerType)
  412. {
  413. string name, ns;
  414. if (type.IsArray)
  415. {
  416. name = GetXmlType (type);
  417. ns = GetXmlNamespace (type, containerType);
  418. }
  419. else
  420. {
  421. name = GetXsdType (type);
  422. if (name != null) return "xsd:" + name;
  423. if (!SoapServices.GetXmlTypeForInteropType (type, out name, out ns))
  424. {
  425. SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (type);
  426. name = att.XmlTypeName;
  427. ns = att.XmlNamespace;
  428. }
  429. }
  430. return GetQualifiedName (tw, ns, name);
  431. }
  432. string GetXmlType (Type type)
  433. {
  434. if (type.IsArray)
  435. {
  436. string itemType = GetXmlType (type.GetElementType ());
  437. itemType = "ArrayOf" + char.ToUpper (itemType[0]) + itemType.Substring (1);
  438. if (type.GetArrayRank () > 1) itemType += type.GetArrayRank ();
  439. return itemType;
  440. }
  441. else
  442. {
  443. string name = null, ns;
  444. name = GetXsdType (type);
  445. if (name != null) return name;
  446. if (SoapServices.GetXmlTypeForInteropType (type, out name, out ns))
  447. return name;
  448. SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (type);
  449. return att.XmlTypeName;
  450. }
  451. }
  452. string GetServiceName (Type t)
  453. {
  454. return t.Name + "Service";
  455. }
  456. string GetPortName (Type t)
  457. {
  458. return t.Name + "Port";
  459. }
  460. string GetBindingName (Type t)
  461. {
  462. return t.Name + "Binding";
  463. }
  464. void FindTypes (ServiceType[] servicetypes, Hashtable dataTypes, ArrayList services)
  465. {
  466. ArrayList mbrTypes = new ArrayList();
  467. foreach (ServiceType st in servicetypes)
  468. FindDataTypes (st.ObjectType, null, dataTypes, mbrTypes);
  469. foreach (Type mbrType in mbrTypes)
  470. {
  471. ServiceType stFound = null;
  472. foreach (ServiceType st in servicetypes)
  473. if (mbrType == st.ObjectType) stFound = st;
  474. if (stFound != null) services.Add (stFound);
  475. else services.Add (new ServiceType (mbrType));
  476. }
  477. }
  478. void FindDataTypes (Type t, Type containerType, Hashtable types, ArrayList services)
  479. {
  480. if (IsSystemType (t))
  481. {
  482. string ns = GetXmlNamespace (t, null);
  483. types [ns] = null;
  484. return;
  485. }
  486. if (!IsService (t))
  487. {
  488. if (!t.IsSerializable) return;
  489. string ns = GetXmlNamespace (t, containerType);
  490. SchemaInfo sinfo = (SchemaInfo) types [ns];
  491. if (sinfo == null)
  492. {
  493. sinfo = new SchemaInfo ();
  494. types [ns] = sinfo;
  495. }
  496. if (sinfo.Types.Contains (t)) return;
  497. sinfo.Types.Add (t);
  498. if (t.IsArray) return;
  499. FieldInfo[] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  500. foreach (FieldInfo fi in fields)
  501. {
  502. string fns = GetXmlNamespace (fi.FieldType, t);
  503. if (!sinfo.Imports.Contains (fns)) sinfo.Imports.Add (fns);
  504. FindDataTypes (fi.FieldType, t, types, services);
  505. }
  506. }
  507. else
  508. {
  509. if (services.Contains (t)) return;
  510. services.Add (t);
  511. foreach (MethodInfo met in t.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
  512. {
  513. ParameterInfo[] pars = met.GetParameters ();
  514. foreach (ParameterInfo par in pars)
  515. FindDataTypes (par.ParameterType, t, types, services);
  516. FindDataTypes (met.ReturnType, t, types, services);
  517. }
  518. }
  519. }
  520. bool IsService (Type t)
  521. {
  522. return t.IsMarshalByRef || t.IsInterface || typeof(Delegate).IsAssignableFrom (t);
  523. }
  524. bool IsSystemType (Type t)
  525. {
  526. return t.FullName.StartsWith ("System.") && !t.IsArray;
  527. }
  528. static string GetXsdType (Type type)
  529. {
  530. if (type.IsEnum) return null;
  531. switch (Type.GetTypeCode (type))
  532. {
  533. case TypeCode.Boolean: return "boolean";
  534. case TypeCode.Byte: return "unsignedByte";
  535. case TypeCode.Char: return "char";
  536. case TypeCode.DateTime: return "dateTime";
  537. case TypeCode.Decimal: return "decimal";
  538. case TypeCode.Double: return "double";
  539. case TypeCode.Int16: return "short";
  540. case TypeCode.Int32: return "int";
  541. case TypeCode.Int64: return "long";
  542. case TypeCode.SByte: return "byte";
  543. case TypeCode.Single: return "float";
  544. case TypeCode.UInt16: return "unsignedShort";
  545. case TypeCode.UInt32: return "unsignedInt";
  546. case TypeCode.UInt64: return "unsignedLong";
  547. case TypeCode.String: return "string";
  548. }
  549. if (type == typeof (TimeSpan))
  550. return "duration";
  551. if (type == typeof (object))
  552. return "anyType";
  553. return null;
  554. }
  555. //
  556. // This is needed, because enumerations from assemblies
  557. // do not report their underlyingtype, but they report
  558. // themselves
  559. //
  560. public static Type EnumToUnderlying (Type t)
  561. {
  562. TypeCode tc = Type.GetTypeCode (t);
  563. switch (tc){
  564. case TypeCode.Boolean:
  565. return typeof (bool);
  566. case TypeCode.Byte:
  567. return typeof (byte);
  568. case TypeCode.SByte:
  569. return typeof (sbyte);
  570. case TypeCode.Int16:
  571. return typeof (short);
  572. case TypeCode.UInt16:
  573. return typeof (ushort);
  574. case TypeCode.Int32:
  575. return typeof (int);
  576. case TypeCode.UInt32:
  577. return typeof (uint);
  578. case TypeCode.Int64:
  579. return typeof (long);
  580. case TypeCode.UInt64:
  581. return typeof (ulong);
  582. }
  583. throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
  584. }
  585. }
  586. class SchemaInfo
  587. {
  588. public ArrayList Types = new ArrayList ();
  589. public ArrayList Imports = new ArrayList ();
  590. public bool SudsGenerated;
  591. }
  592. }