PageRenderTime 67ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Web.Extensions/System.Web.Script.Services/LogicalTypeInfo.cs

https://bitbucket.org/danipen/mono
C# | 699 lines | 548 code | 113 blank | 38 comment | 101 complexity | bb07193d570a4de43c0b60343ce813fd MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // LogicalTypeInfo.cs
  3. //
  4. // Author:
  5. // Konstantin Triger <kostat@mainsoft.com>
  6. // Atsushi Enomoto <atsushi@ximian.com>
  7. //
  8. // (C) 2007 Mainsoft, Inc. http://www.mainsoft.com
  9. // Copyright (C) 2009 Novell, Inc. http://novell.com
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Collections.Generic;
  33. using System.Collections.Specialized;
  34. using System.Text;
  35. using System.Web.Services;
  36. using System.Reflection;
  37. using System.Collections;
  38. using System.Web.Script.Serialization;
  39. using System.IO;
  40. using System.Xml.Serialization;
  41. using System.Xml;
  42. #if NET_3_5
  43. using System.ServiceModel;
  44. using System.ServiceModel.Description;
  45. #endif
  46. namespace System.Web.Script.Services
  47. {
  48. internal sealed class JsonResult
  49. {
  50. public readonly object d;
  51. public JsonResult (object result) {
  52. d = result;
  53. }
  54. }
  55. internal abstract class LogicalTypeInfo
  56. {
  57. public static LogicalTypeInfo CreateTypeInfo (Type t, string filePath)
  58. {
  59. #if NET_3_5
  60. if (t.GetCustomAttributes (typeof (ServiceContractAttribute), false).Length > 0)
  61. return new WcfLogicalTypeInfo (t, filePath);
  62. else
  63. #endif
  64. return new AsmxLogicalTypeInfo (t, filePath);
  65. }
  66. internal abstract class LogicalMethodInfo
  67. {
  68. readonly MethodInfo _methodInfo;
  69. internal readonly ParameterInfo [] _params;
  70. internal readonly Dictionary<string, int> _paramMap;
  71. LogicalTypeInfo _typeInfo;
  72. protected LogicalMethodInfo (LogicalTypeInfo typeInfo, MethodInfo method)
  73. {
  74. _methodInfo = method;
  75. _params = MethodInfo.GetParameters ();
  76. _typeInfo = typeInfo;
  77. if (HasParameters) {
  78. _paramMap = new Dictionary<string, int> (_params.Length, StringComparer.Ordinal);
  79. for (int i = 0; i < _params.Length; i++)
  80. _paramMap.Add(_params[i].Name, i);
  81. }
  82. }
  83. public abstract bool UseHttpGet { get; }
  84. public abstract bool EnableSession { get; }
  85. public abstract ResponseFormat ResponseFormat { get; }
  86. public abstract string MethodName { get; }
  87. public MethodInfo MethodInfo { get { return _methodInfo; } }
  88. public bool HasParameters { get { return _params != null && _params.Length > 0; } }
  89. public IEnumerable<Type> GetParameterTypes () {
  90. if (HasParameters)
  91. for (int i = 0; i < _params.Length; i++)
  92. yield return _params [i].ParameterType;
  93. yield return MethodInfo.ReturnType;
  94. }
  95. public void GenerateMethod (StringBuilder proxy, bool isPrototype, bool isPage) {
  96. string ns;
  97. string service;// = isPage ? "PageMethods" : MethodInfo.DeclaringType.FullName;
  98. _typeInfo.GetNamespaceAndServiceName (MethodInfo.DeclaringType, isPage, out ns, out service);
  99. string useHttpGet = UseHttpGet ? "true" : "false";
  100. string paramMap = GenerateParameters (true);
  101. string paramList = GenerateParameters (false);
  102. if (isPrototype){
  103. proxy.AppendFormat (
  104. @"
  105. {1}:function({4}succeededCallback, failedCallback, userContext) {{
  106. return this._invoke({0}.get_path(), '{1}',{2},{{{3}}},succeededCallback,failedCallback,userContext); }}",
  107. service, MethodName, useHttpGet, paramMap, paramList);
  108. }
  109. else
  110. proxy.AppendFormat (
  111. @"
  112. {0}.{1}= function({2}onSuccess,onFailed,userContext) {{{0}._staticInstance.{1}({2}onSuccess,onFailed,userContext); }}",
  113. service, MethodName, paramList);
  114. }
  115. string GenerateParameters (bool isMap) {
  116. if (!HasParameters)
  117. return null;
  118. StringBuilder builder = new StringBuilder ();
  119. for (int i = 0; i < _params.Length; i++) {
  120. builder.AppendFormat (isMap ? "{0}:{0}" : "{0}", _params [i].Name);
  121. builder.Append (',');
  122. }
  123. if (isMap)
  124. builder.Length--;
  125. return builder.ToString ();
  126. }
  127. public abstract void Invoke (HttpRequest request, HttpResponse response);
  128. }
  129. #if !TARGET_J2EE
  130. static Hashtable _type_to_logical_type = Hashtable.Synchronized (new Hashtable ());
  131. #else
  132. const string type_to_logical_type_key = "System.Web.Script.Services.LogicalTypeInfo";
  133. static Hashtable _type_to_logical_type {
  134. get {
  135. Hashtable hash = (Hashtable) AppDomain.CurrentDomain.GetData (type_to_logical_type_key);
  136. if (hash != null)
  137. return hash;
  138. AppDomain.CurrentDomain.SetData (type_to_logical_type_key, Hashtable.Synchronized (new Hashtable ()));
  139. return (Hashtable) AppDomain.CurrentDomain.GetData (type_to_logical_type_key);
  140. }
  141. }
  142. #endif
  143. static internal LogicalTypeInfo GetLogicalTypeInfo (Type t, string filePath) {
  144. Hashtable type_to_manager = _type_to_logical_type;
  145. LogicalTypeInfo tm = (LogicalTypeInfo) type_to_manager [t];
  146. if (tm != null)
  147. return tm;
  148. tm = CreateTypeInfo (t, filePath);
  149. type_to_manager [t] = tm;
  150. return tm;
  151. }
  152. protected static string EnsureNamespaceRegistered (string ns, string name, StringBuilder proxy, List<string> registeredNamespaces) {
  153. if (String.IsNullOrEmpty (ns))
  154. return "var " + name;
  155. if (!registeredNamespaces.Contains (ns)) {
  156. registeredNamespaces.Add (ns);
  157. proxy.AppendFormat (
  158. @"
  159. Type.registerNamespace('{0}');",
  160. ns);
  161. }
  162. return name;
  163. }
  164. protected virtual void GetNamespaceAndServiceName (Type type, bool isPage, out string ns, out string service)
  165. {
  166. ns = isPage ? String.Empty : type.Namespace;
  167. service = isPage ? "PageMethods" : type.FullName;
  168. }
  169. // instance members
  170. internal readonly Type _type;
  171. readonly string _proxy;
  172. internal readonly Hashtable _methodMap;
  173. protected LogicalTypeInfo (Type t, string filePath)
  174. {
  175. _type = t;
  176. bool isPage = _type.IsSubclassOf (typeof (System.Web.UI.Page));
  177. var logicalMethods = GetLogicalMethods (isPage);
  178. //_logicalMethods = (LogicalMethodInfo []) list.ToArray (typeof (LogicalMethodInfo));
  179. _methodMap = new Hashtable (logicalMethods.Count);
  180. for (int i = 0; i < logicalMethods.Count; i++)
  181. _methodMap.Add (logicalMethods [i].MethodName, logicalMethods [i]);
  182. string ns;
  183. string service;
  184. GetNamespaceAndServiceName (t, isPage, out ns, out service);
  185. StringBuilder proxy = new StringBuilder ();
  186. List<string> registeredNamespaces = new List<string> ();
  187. string scriptTypeDeclaration = EnsureNamespaceRegistered (ns, service, proxy, registeredNamespaces);
  188. proxy.AppendFormat (
  189. @"
  190. " + scriptTypeDeclaration + @"=function() {{
  191. {0}.initializeBase(this);
  192. this._timeout = 0;
  193. this._userContext = null;
  194. this._succeeded = null;
  195. this._failed = null;
  196. }}
  197. {0}.prototype={{",
  198. service);
  199. for (int i = 0; i < logicalMethods.Count; i++) {
  200. if (i > 0)
  201. proxy.Append (',');
  202. logicalMethods [i].GenerateMethod (proxy, true, isPage);
  203. }
  204. proxy.AppendFormat (
  205. @"}}
  206. {0}.registerClass('{0}',Sys.Net.WebServiceProxy);
  207. {0}._staticInstance = new {0}();
  208. {0}.set_path = function(value) {{ {0}._staticInstance.set_path(value); }}
  209. {0}.get_path = function() {{ return {0}._staticInstance.get_path(); }}
  210. {0}.set_timeout = function(value) {{ {0}._staticInstance.set_timeout(value); }}
  211. {0}.get_timeout = function() {{ return {0}._staticInstance.get_timeout(); }}
  212. {0}.set_defaultUserContext = function(value) {{ {0}._staticInstance.set_defaultUserContext(value); }}
  213. {0}.get_defaultUserContext = function() {{ return {0}._staticInstance.get_defaultUserContext(); }}
  214. {0}.set_defaultSucceededCallback = function(value) {{ {0}._staticInstance.set_defaultSucceededCallback(value); }}
  215. {0}.get_defaultSucceededCallback = function() {{ return {0}._staticInstance.get_defaultSucceededCallback(); }}
  216. {0}.set_defaultFailedCallback = function(value) {{ {0}._staticInstance.set_defaultFailedCallback(value); }}
  217. {0}.get_defaultFailedCallback = function() {{ return {0}._staticInstance.get_defaultFailedCallback(); }}
  218. {0}.set_path(""{1}"");",
  219. service, filePath);
  220. for (int i = 0; i < logicalMethods.Count; i++)
  221. logicalMethods [i].GenerateMethod (proxy, false, isPage);
  222. GenerateTypeRegistrationScript (proxy, registeredNamespaces);
  223. proxy.AppendLine ();
  224. _proxy = proxy.ToString ();
  225. }
  226. protected IEnumerable<MemberInfo> GetGenerateScriptTypes () {
  227. foreach (LogicalMethodInfo lmi in _methodMap.Values)
  228. yield return lmi.MethodInfo;
  229. yield return _type;
  230. }
  231. protected static void GenerateTypeRegistrationScript (StringBuilder proxy, Type scriptType, string scriptTypeId, List<string> registeredNamespaces) {
  232. string className = scriptType.FullName.Replace ('+', '_');
  233. string ns = scriptType.Namespace;
  234. string scriptTypeDeclaration = EnsureNamespaceRegistered (ns, className, proxy, registeredNamespaces);
  235. proxy.AppendFormat (
  236. @"
  237. if (typeof({0}) === 'undefined') {{", className);
  238. if (scriptType.IsEnum) {
  239. proxy.AppendFormat (
  240. @"
  241. {0} = function() {{ throw Error.invalidOperation(); }}
  242. {0}.prototype = {1}
  243. {0}.registerEnum('{0}', {2});",
  244. className,
  245. // This method is also used for WCF, but for enum this should work ...
  246. AsmxLogicalTypeInfo.JSSerializer.Serialize(GetEnumPrototypeDictionary (scriptType)),
  247. Attribute.GetCustomAttribute (scriptType, typeof (FlagsAttribute)) != null ? "true" : "false");
  248. }
  249. else {
  250. string typeId = String.IsNullOrEmpty (scriptTypeId) ? scriptType.FullName : scriptTypeId;
  251. proxy.AppendFormat (
  252. @"
  253. " + scriptTypeDeclaration + @"=gtc(""{1}"");
  254. {0}.registerClass('{0}');",
  255. className, typeId);
  256. }
  257. proxy.Append ('}');
  258. }
  259. static IDictionary <string, object> GetEnumPrototypeDictionary (Type type)
  260. {
  261. var ret = new Dictionary <string, object> ();
  262. string [] names = Enum.GetNames (type);
  263. Array values = Enum.GetValues (type);
  264. for (int i = 0; i < names.Length; i++)
  265. ret.Add (names [i], values.GetValue (i));
  266. return ret;
  267. }
  268. static readonly Type typeOfIEnumerable = typeof (IEnumerable);
  269. static readonly Type typeOfIDictionary = typeof (IDictionary);
  270. protected static bool ShouldGenerateScript (Type type, bool throwIfNot) {
  271. if (type.IsEnum)
  272. return true;
  273. if (Type.GetTypeCode (type) != TypeCode.Object)
  274. return false;
  275. if (type == typeof (void))
  276. return false;
  277. if (typeOfIEnumerable.IsAssignableFrom (type) ||
  278. typeOfIDictionary.IsAssignableFrom (type) ||
  279. type.IsAbstract || type.IsInterface) {
  280. if (throwIfNot)
  281. ThrowOnIncorrectGenerateScriptAttribute ();
  282. return false;
  283. }
  284. // LAMESPEC: MS never create proxies for GenericTypes
  285. //&& type.GetGenericTypeDefinition ().GetGenericArguments ().Length > 1
  286. if (type.IsGenericType)
  287. return false;
  288. ConstructorInfo ci = type.GetConstructor (Type.EmptyTypes);
  289. if (ci == null || !ci.IsPublic) {
  290. if (throwIfNot)
  291. ThrowOnIncorrectGenerateScriptAttribute ();
  292. return false;
  293. }
  294. return true;
  295. }
  296. static void ThrowOnIncorrectGenerateScriptAttribute () {
  297. throw new InvalidOperationException (
  298. "Using the GenerateScriptTypes attribute is not supported for types in the following categories: primitive types; DateTime; generic types taking more than one parameter; types implementing IEnumerable or IDictionary; interfaces; Abstract classes; classes without a public default constructor.");
  299. }
  300. protected abstract void GenerateTypeRegistrationScript (StringBuilder proxy, List<string> registeredNamespaces);
  301. protected abstract List<LogicalMethodInfo> GetLogicalMethods (bool isPage);
  302. public string Proxy { get { return _proxy; } }
  303. public LogicalMethodInfo this [string method] {
  304. get { return (LogicalMethodInfo) _methodMap [method]; }
  305. }
  306. }
  307. internal sealed class AsmxLogicalTypeInfo : LogicalTypeInfo
  308. {
  309. #region LogicalMethodInfo
  310. public sealed class AsmxLogicalMethodInfo : LogicalTypeInfo.LogicalMethodInfo
  311. {
  312. readonly LogicalTypeInfo _typeInfo;
  313. readonly WebMethodAttribute _wma;
  314. readonly ScriptMethodAttribute _sma;
  315. readonly XmlSerializer _xmlSer;
  316. public AsmxLogicalMethodInfo (LogicalTypeInfo typeInfo, MethodInfo method)
  317. : base (typeInfo, method)
  318. {
  319. _typeInfo = typeInfo;
  320. _wma = (WebMethodAttribute) Attribute.GetCustomAttribute (method, typeof (WebMethodAttribute));
  321. _sma = (ScriptMethodAttribute) Attribute.GetCustomAttribute (method, typeof (ScriptMethodAttribute));
  322. if (_sma == null)
  323. _sma = ScriptMethodAttribute.Default;
  324. if (ScriptMethod.ResponseFormat == ResponseFormat.Xml
  325. && MethodInfo.ReturnType != typeof (void)) {
  326. Type retType = MethodInfo.ReturnType;
  327. if (Type.GetTypeCode (retType) != TypeCode.String || ScriptMethod.XmlSerializeString)
  328. _xmlSer = new XmlSerializer (retType);
  329. }
  330. }
  331. IDictionary<string,object> BuildInvokeParameters (HttpRequest request)
  332. {
  333. return "GET".Equals (request.RequestType, StringComparison.OrdinalIgnoreCase) ?
  334. GetNameValueCollectionDictionary (request.QueryString) :
  335. (IDictionary<string, object>) JavaScriptSerializer.DefaultSerializer.DeserializeObjectInternal (new StreamReader (request.InputStream, request.ContentEncoding));
  336. }
  337. IDictionary <string, object> GetNameValueCollectionDictionary (NameValueCollection nvc)
  338. {
  339. var ret = new Dictionary <string, object> ();
  340. for (int i = nvc.Count - 1; i >= 0; i--)
  341. ret.Add (nvc.GetKey (i), JavaScriptSerializer.DefaultSerializer.DeserializeObjectInternal (nvc.Get (i)));
  342. return ret;
  343. }
  344. public override void Invoke (HttpRequest request, HttpResponse response) {
  345. var writer = response.Output;
  346. IDictionary<string, object> @params = BuildInvokeParameters (request);
  347. object [] pp = null;
  348. if (HasParameters) {
  349. Type ptype;
  350. int i;
  351. object value;
  352. pp = new object [_params.Length];
  353. foreach (KeyValuePair<string, object> pair in @params) {
  354. if (!_paramMap.TryGetValue (pair.Key, out i))
  355. continue;
  356. value = pair.Value;
  357. ptype = _params [i].ParameterType;
  358. if (ptype == typeof (System.Object))
  359. pp [i] = value;
  360. else
  361. pp [i] = AsmxLogicalTypeInfo.JSSerializer.ConvertToType (value, ptype);
  362. }
  363. }
  364. object target = MethodInfo.IsStatic ? null : Activator.CreateInstance (_typeInfo._type);
  365. object result = MethodInfo.Invoke (target, pp);
  366. if (_xmlSer != null) {
  367. XmlTextWriter xwriter = new XmlTextWriter (writer);
  368. xwriter.Formatting = Formatting.None;
  369. _xmlSer.Serialize (xwriter, result);
  370. }
  371. else
  372. {
  373. result = new JsonResult (result);
  374. AsmxLogicalTypeInfo.JSSerializer.Serialize (result, writer);
  375. }
  376. }
  377. public override string MethodName { get { return String.IsNullOrEmpty (WebMethod.MessageName) ? MethodInfo.Name : WebMethod.MessageName; } }
  378. public ScriptMethodAttribute ScriptMethod { get { return _sma; } }
  379. public WebMethodAttribute WebMethod { get { return _wma; } }
  380. public override bool UseHttpGet { get { return ScriptMethod.UseHttpGet; } }
  381. public override bool EnableSession { get { return WebMethod.EnableSession; } }
  382. public override ResponseFormat ResponseFormat { get { return ScriptMethod.ResponseFormat; } }
  383. }
  384. #endregion
  385. //readonly LogicalMethodInfo [] _logicalMethods;
  386. internal static readonly JavaScriptSerializer JSSerializer = new JavaScriptSerializer (null, true);
  387. protected override List<LogicalMethodInfo> GetLogicalMethods (bool isPage)
  388. {
  389. BindingFlags bindingAttr = isPage ? (BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public) : (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  390. MethodInfo [] all_type_methods = _type.GetMethods (bindingAttr);
  391. List<LogicalMethodInfo> logicalMethods = new List<LogicalMethodInfo> (all_type_methods.Length);
  392. foreach (MethodInfo mi in all_type_methods) {
  393. if (mi.IsPublic &&
  394. mi.GetCustomAttributes (typeof (WebMethodAttribute), false).Length > 0)
  395. logicalMethods.Add (new AsmxLogicalMethodInfo (this, mi));
  396. else {
  397. foreach (Type ifaceType in _type.GetInterfaces ()) {
  398. if (ifaceType.GetCustomAttributes (typeof (WebServiceBindingAttribute), false).Length > 0) {
  399. MethodInfo found = FindInInterface (ifaceType, mi);
  400. if (found != null) {
  401. if (found.GetCustomAttributes (typeof (WebMethodAttribute), false).Length > 0)
  402. logicalMethods.Add (new AsmxLogicalMethodInfo (this, found));
  403. break;
  404. }
  405. }
  406. }
  407. }
  408. }
  409. return logicalMethods;
  410. }
  411. internal AsmxLogicalTypeInfo (Type t, string filePath)
  412. : base (t, filePath)
  413. {
  414. }
  415. IEnumerable<GenerateScriptTypeAttribute> GetGenerateScriptTypeAttributes () {
  416. Hashtable generatedTypes = new Hashtable ();
  417. foreach (MemberInfo mi in GetGenerateScriptTypes ()) {
  418. GenerateScriptTypeAttribute [] gstas = (GenerateScriptTypeAttribute []) mi.GetCustomAttributes (typeof (GenerateScriptTypeAttribute), true);
  419. if (gstas == null || gstas.Length == 0)
  420. continue;
  421. for (int i = 0; i < gstas.Length; i++) {
  422. if (!generatedTypes.Contains (gstas [i].Type)) {
  423. if (ShouldGenerateScript (gstas [i].Type, true)) {
  424. generatedTypes [gstas [i].Type] = gstas [i].Type;
  425. yield return gstas [i];
  426. }
  427. }
  428. }
  429. }
  430. foreach (LogicalMethodInfo lmi in _methodMap.Values) {
  431. foreach (Type t in lmi.GetParameterTypes ()) {
  432. Type param = GetTypeToGenerate (t);
  433. if (!generatedTypes.Contains (param)) {
  434. if (ShouldGenerateScript (param, false)) {
  435. generatedTypes [param] = param;
  436. yield return new GenerateScriptTypeAttribute (param);
  437. }
  438. }
  439. }
  440. }
  441. }
  442. static Type GetTypeToGenerate (Type type) {
  443. if (type.IsArray)
  444. return type.GetElementType ();
  445. if (type.IsGenericType) {
  446. while (type.IsGenericType && type.GetGenericArguments ().Length == 1)
  447. type = type.GetGenericArguments () [0];
  448. return type;
  449. }
  450. return type;
  451. }
  452. static MethodInfo FindInInterface (Type ifaceType, MethodInfo method) {
  453. int nameStartIndex = 0;
  454. if (method.IsPrivate) {
  455. nameStartIndex = method.Name.LastIndexOf ('.');
  456. if (nameStartIndex < 0)
  457. nameStartIndex = 0;
  458. else {
  459. if (String.CompareOrdinal (
  460. ifaceType.FullName.Replace ('+', '.'), 0, method.Name, 0, nameStartIndex) != 0)
  461. return null;
  462. nameStartIndex++;
  463. }
  464. }
  465. foreach (MethodInfo mi in ifaceType.GetMembers ()) {
  466. if (method.ReturnType == mi.ReturnType &&
  467. String.CompareOrdinal (method.Name, nameStartIndex, mi.Name, 0, mi.Name.Length) == 0) {
  468. ParameterInfo [] rpi = method.GetParameters ();
  469. ParameterInfo [] lpi = mi.GetParameters ();
  470. if (rpi.Length == lpi.Length) {
  471. bool match = true;
  472. for (int i = 0; i < rpi.Length; i++) {
  473. if (rpi [i].ParameterType != lpi [i].ParameterType) {
  474. match = false;
  475. break;
  476. }
  477. }
  478. if (match)
  479. return mi;
  480. }
  481. }
  482. }
  483. return null;
  484. }
  485. protected override void GenerateTypeRegistrationScript (StringBuilder proxy, List<string> registeredNamespaces)
  486. {
  487. bool gtc = false;
  488. foreach (GenerateScriptTypeAttribute gsta in GetGenerateScriptTypeAttributes ()) {
  489. if (!gtc && !gsta.Type.IsEnum) {
  490. proxy.Append (
  491. @"
  492. var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;");
  493. gtc = true;
  494. }
  495. GenerateTypeRegistrationScript (proxy, gsta.Type, gsta.ScriptTypeId, registeredNamespaces);
  496. }
  497. }
  498. }
  499. #if NET_3_5
  500. internal class WcfLogicalTypeInfo : LogicalTypeInfo
  501. {
  502. ContractDescription cd;
  503. public WcfLogicalTypeInfo (Type type, string filePath)
  504. : base (type, filePath)
  505. {
  506. }
  507. ContractDescription Contract {
  508. get {
  509. if (cd == null)
  510. cd = ContractDescription.GetContract (_type);
  511. return cd;
  512. }
  513. }
  514. IEnumerable<KeyValuePair<Type,string>> GetDataContractTypeInfos ()
  515. {
  516. foreach (var od in Contract.Operations) {
  517. foreach (var md in od.Messages) {
  518. foreach (var pd in md.Body.Parts) {
  519. if (ShouldGenerateScript (pd.Type, false))
  520. yield return new KeyValuePair<Type,string> (pd.Type, null);
  521. }
  522. if (md.Body.ReturnValue != null && ShouldGenerateScript (md.Body.ReturnValue.Type, false))
  523. yield return new KeyValuePair<Type,string> (md.Body.ReturnValue.Type, null);
  524. }
  525. }
  526. yield break;
  527. }
  528. protected override void GetNamespaceAndServiceName (Type type, bool isPage, out string ns, out string service)
  529. {
  530. string name = type.Namespace;
  531. int dot = name.LastIndexOf ('.');
  532. if (dot > -1)
  533. name = name.Substring (dot + 1);
  534. ns = name;
  535. service = name + "." + type.Name;
  536. }
  537. protected override void GenerateTypeRegistrationScript (StringBuilder proxy, List<string> registeredNamespaces)
  538. {
  539. bool gtc = false;
  540. foreach (KeyValuePair<Type,string> pair in GetDataContractTypeInfos ()) {
  541. if (!gtc && !pair.Key.IsEnum) {
  542. proxy.Append (
  543. @"
  544. var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;");
  545. gtc = true;
  546. }
  547. GenerateTypeRegistrationScript (proxy, pair.Key, pair.Value, registeredNamespaces);
  548. }
  549. }
  550. protected override List<LogicalMethodInfo> GetLogicalMethods (bool isPage)
  551. {
  552. if (isPage)
  553. throw new NotSupportedException ();
  554. var l = new List<LogicalMethodInfo> ();
  555. foreach (var od in Contract.Operations)
  556. l.Add (new WcfLogicalMethodInfo (this, od));
  557. return l;
  558. }
  559. internal class WcfLogicalMethodInfo : LogicalMethodInfo
  560. {
  561. OperationDescription od;
  562. public WcfLogicalMethodInfo (LogicalTypeInfo typeInfo, OperationDescription od)
  563. : base (typeInfo, od.SyncMethod)
  564. {
  565. this.od = od;
  566. }
  567. public override bool UseHttpGet { get { return true; } } // always
  568. // FIXME: could this be enabled?
  569. public override bool EnableSession {
  570. get { return false; }
  571. }
  572. public override ResponseFormat ResponseFormat {
  573. get { return ResponseFormat.Json; } // always
  574. }
  575. public override string MethodName {
  576. get { return od.Name; }
  577. }
  578. public override void Invoke (HttpRequest request, HttpResponse response)
  579. {
  580. // invocation is done in WCF part.
  581. throw new NotSupportedException ();
  582. }
  583. }
  584. }
  585. #endif
  586. }