OperationGenerator.cs 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Description
  5. {
  6. using System.CodeDom;
  7. using System.Collections.Generic;
  8. using System.Net.Security;
  9. using System.Reflection;
  10. using System.Runtime;
  11. using System.Runtime.Serialization;
  12. using System.ServiceModel.Channels;
  13. using System.ServiceModel.Security;
  14. using System.ComponentModel;
  15. using System.Threading.Tasks;
  16. enum MessageContractType { None, WrappedMessageContract, BareMessageContract }
  17. interface IWrappedBodyTypeGenerator
  18. {
  19. void ValidateForParameterMode(OperationDescription operationDescription);
  20. void AddMemberAttributes(XmlName messageName, MessagePartDescription part, CodeAttributeDeclarationCollection attributesImported, CodeAttributeDeclarationCollection typeAttributes, CodeAttributeDeclarationCollection fieldAttributes);
  21. void AddTypeAttributes(string messageName, string typeNS, CodeAttributeDeclarationCollection typeAttributes, bool isEncoded);
  22. }
  23. class OperationGenerator //: IOperationBehavior, IOperationContractGenerationExtension
  24. {
  25. Dictionary<MessagePartDescription, CodeTypeReference> parameterTypes;
  26. Dictionary<MessagePartDescription, CodeAttributeDeclarationCollection> parameterAttributes;
  27. Dictionary<MessagePartDescription, string> specialPartName;
  28. internal OperationGenerator()
  29. {
  30. }
  31. internal Dictionary<MessagePartDescription, CodeAttributeDeclarationCollection> ParameterAttributes
  32. {
  33. get
  34. {
  35. if (this.parameterAttributes == null)
  36. this.parameterAttributes = new Dictionary<MessagePartDescription, CodeAttributeDeclarationCollection>();
  37. return this.parameterAttributes;
  38. }
  39. }
  40. internal Dictionary<MessagePartDescription, CodeTypeReference> ParameterTypes
  41. {
  42. get
  43. {
  44. if (this.parameterTypes == null)
  45. this.parameterTypes = new Dictionary<MessagePartDescription, CodeTypeReference>();
  46. return this.parameterTypes;
  47. }
  48. }
  49. internal Dictionary<MessagePartDescription, string> SpecialPartName
  50. {
  51. get
  52. {
  53. if (specialPartName == null)
  54. this.specialPartName = new Dictionary<MessagePartDescription, string>();
  55. return specialPartName;
  56. }
  57. }
  58. internal void GenerateOperation(OperationContractGenerationContext context, ref OperationFormatStyle style, bool isEncoded, IWrappedBodyTypeGenerator wrappedBodyTypeGenerator, Dictionary<MessagePartDescription, ICollection<CodeTypeReference>> knownTypes)
  59. {
  60. if (context == null)
  61. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("context"));
  62. if (context.Operation == null)
  63. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OperationPropertyIsRequiredForAttributeGeneration)));
  64. MethodSignatureGenerator methodSignatureGenerator = new MethodSignatureGenerator(this, context, style, isEncoded, wrappedBodyTypeGenerator, knownTypes);
  65. methodSignatureGenerator.GenerateSyncSignature(ref style);
  66. if (context.IsTask)
  67. {
  68. methodSignatureGenerator.GenerateTaskSignature(ref style);
  69. }
  70. if (context.IsAsync)
  71. {
  72. methodSignatureGenerator.GenerateAsyncSignature(ref style);
  73. }
  74. }
  75. internal static CodeAttributeDeclaration GenerateAttributeDeclaration(ServiceContractGenerator generator, Attribute attribute)
  76. {
  77. return CustomAttributeHelper.GenerateAttributeDeclaration(generator, attribute);
  78. }
  79. class MethodSignatureGenerator
  80. {
  81. readonly OperationGenerator Parent;
  82. readonly OperationContractGenerationContext Context;
  83. readonly OperationFormatStyle Style;
  84. readonly bool IsEncoded;
  85. readonly IWrappedBodyTypeGenerator WrappedBodyTypeGenerator;
  86. readonly Dictionary<MessagePartDescription, ICollection<CodeTypeReference>> KnownTypes;
  87. CodeMemberMethod Method;
  88. CodeMemberMethod EndMethod;
  89. readonly string ContractName;
  90. string DefaultName;
  91. readonly string ContractNS;
  92. readonly string DefaultNS;
  93. readonly bool Oneway;
  94. readonly MessageDescription Request;
  95. readonly MessageDescription Response;
  96. bool IsNewRequest;
  97. bool IsNewResponse;
  98. bool IsTaskWithOutputParameters;
  99. MessageContractType MessageContractType;
  100. IPartCodeGenerator BeginPartCodeGenerator;
  101. IPartCodeGenerator EndPartCodeGenerator;
  102. internal MethodSignatureGenerator(OperationGenerator parent, OperationContractGenerationContext context, OperationFormatStyle style, bool isEncoded, IWrappedBodyTypeGenerator wrappedBodyTypeGenerator, Dictionary<MessagePartDescription, ICollection<CodeTypeReference>> knownTypes)
  103. {
  104. this.Parent = parent;
  105. this.Context = context;
  106. this.Style = style;
  107. this.IsEncoded = isEncoded;
  108. this.WrappedBodyTypeGenerator = wrappedBodyTypeGenerator;
  109. this.KnownTypes = knownTypes;
  110. this.MessageContractType = context.ServiceContractGenerator.OptionsInternal.IsSet(ServiceContractGenerationOptions.TypedMessages) ? MessageContractType.WrappedMessageContract : MessageContractType.None;
  111. this.ContractName = context.Contract.Contract.CodeName;
  112. this.ContractNS = context.Operation.DeclaringContract.Namespace;
  113. this.DefaultNS = (style == OperationFormatStyle.Rpc) ? string.Empty : this.ContractNS;
  114. this.Oneway = (context.Operation.IsOneWay);
  115. this.Request = context.Operation.Messages[0];
  116. this.Response = this.Oneway ? null : context.Operation.Messages[1];
  117. this.IsNewRequest = true;
  118. this.IsNewResponse = true;
  119. this.BeginPartCodeGenerator = null;
  120. this.EndPartCodeGenerator = null;
  121. this.IsTaskWithOutputParameters = context.IsTask && context.Operation.HasOutputParameters;
  122. Fx.Assert(this.Oneway == (this.Response == null), "OperationContractGenerationContext.Operation cannot contain a null response message when the operation is not one-way");
  123. }
  124. internal void GenerateSyncSignature(ref OperationFormatStyle style)
  125. {
  126. this.Method = this.Context.SyncMethod;
  127. this.EndMethod = this.Context.SyncMethod;
  128. this.DefaultName = this.Method.Name;
  129. GenerateOperationSignatures(ref style);
  130. }
  131. internal void GenerateAsyncSignature(ref OperationFormatStyle style)
  132. {
  133. this.Method = this.Context.BeginMethod;
  134. this.EndMethod = this.Context.EndMethod;
  135. this.DefaultName = this.Method.Name.Substring(5);
  136. GenerateOperationSignatures(ref style);
  137. }
  138. void GenerateOperationSignatures(ref OperationFormatStyle style)
  139. {
  140. if (this.MessageContractType != MessageContractType.None || this.GenerateTypedMessageForTaskWithOutputParameters())
  141. {
  142. CheckAndSetMessageContractTypeToBare();
  143. this.GenerateTypedMessageOperation(false /*hideFromEditor*/, ref style);
  144. }
  145. else if (!this.TryGenerateParameterizedOperation())
  146. {
  147. this.GenerateTypedMessageOperation(true /*hideFromEditor*/, ref style);
  148. }
  149. }
  150. bool GenerateTypedMessageForTaskWithOutputParameters()
  151. {
  152. if (this.IsTaskWithOutputParameters)
  153. {
  154. if (this.Method == this.Context.TaskMethod)
  155. {
  156. this.Method.Comments.Add(new CodeCommentStatement(SR.GetString(SR.SFxCodeGenWarning, SR.GetString(SR.SFxCannotImportAsParameters_OutputParameterAndTask))));
  157. }
  158. return true;
  159. }
  160. return false;
  161. }
  162. void CheckAndSetMessageContractTypeToBare()
  163. {
  164. if (this.MessageContractType == MessageContractType.BareMessageContract)
  165. return;
  166. try
  167. {
  168. this.WrappedBodyTypeGenerator.ValidateForParameterMode(this.Context.Operation);
  169. }
  170. catch (ParameterModeException ex)
  171. {
  172. this.MessageContractType = ex.MessageContractType;
  173. }
  174. }
  175. bool TryGenerateParameterizedOperation()
  176. {
  177. CodeParameterDeclarationExpressionCollection methodParameters, endMethodParameters = null;
  178. methodParameters = new CodeParameterDeclarationExpressionCollection(this.Method.Parameters);
  179. if (this.EndMethod != null)
  180. endMethodParameters = new CodeParameterDeclarationExpressionCollection(this.EndMethod.Parameters);
  181. try
  182. {
  183. GenerateParameterizedOperation();
  184. }
  185. catch (ParameterModeException ex)
  186. {
  187. this.MessageContractType = ex.MessageContractType;
  188. CodeMemberMethod method = this.Method;
  189. method.Comments.Add(new CodeCommentStatement(SR.GetString(SR.SFxCodeGenWarning, ex.Message)));
  190. method.Parameters.Clear();
  191. method.Parameters.AddRange(methodParameters);
  192. if (this.Context.IsAsync)
  193. {
  194. CodeMemberMethod endMethod = this.EndMethod;
  195. endMethod.Parameters.Clear();
  196. endMethod.Parameters.AddRange(endMethodParameters);
  197. }
  198. return false;
  199. }
  200. return true;
  201. }
  202. void GenerateParameterizedOperation()
  203. {
  204. ParameterizedMessageHelper.ValidateProtectionLevel(this);
  205. CreateOrOverrideActionProperties();
  206. if (this.HasUntypedMessages)
  207. {
  208. if (!this.IsCompletelyUntyped)
  209. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_Message, this.Context.Operation.CodeName)));
  210. CreateUntypedMessages();
  211. }
  212. else
  213. {
  214. ParameterizedMessageHelper.ValidateWrapperSettings(this);
  215. ParameterizedMessageHelper.ValidateNoHeaders(this);
  216. this.WrappedBodyTypeGenerator.ValidateForParameterMode(this.Context.Operation);
  217. ParameterizedMethodGenerator generator = new ParameterizedMethodGenerator(this.Method, this.EndMethod);
  218. this.BeginPartCodeGenerator = generator.InputGenerator;
  219. this.EndPartCodeGenerator = generator.OutputGenerator;
  220. if (!this.Oneway && this.Response.Body.ReturnValue != null)
  221. {
  222. this.EndMethod.ReturnType = GetParameterType(this.Response.Body.ReturnValue);
  223. ParameterizedMessageHelper.GenerateMessageParameterAttribute(this.Response.Body.ReturnValue, this.EndMethod.ReturnTypeCustomAttributes, TypeLoader.GetReturnValueName(this.DefaultName), this.DefaultNS);
  224. AddAdditionalAttributes(this.Response.Body.ReturnValue, this.EndMethod.ReturnTypeCustomAttributes, this.IsEncoded);
  225. }
  226. GenerateMessageBodyParts(false /*generateTypedMessages*/);
  227. }
  228. }
  229. void GenerateTypedMessageOperation(bool hideFromEditor, ref OperationFormatStyle style)
  230. {
  231. CreateOrOverrideActionProperties();
  232. if (this.HasUntypedMessages)
  233. {
  234. CreateUntypedMessages();
  235. if (this.IsCompletelyUntyped)
  236. return;
  237. }
  238. CodeNamespace ns = this.Context.ServiceContractGenerator.NamespaceManager.EnsureNamespace(this.ContractNS);
  239. if (!this.Request.IsUntypedMessage)
  240. {
  241. CodeTypeReference typedReqMessageRef = GenerateTypedMessageHeaderAndReturnValueParts(ns, this.DefaultName + "Request", this.Request, false /*isReply*/, hideFromEditor, ref this.IsNewRequest, out this.BeginPartCodeGenerator);
  242. this.Method.Parameters.Insert(0, new CodeParameterDeclarationExpression(typedReqMessageRef, "request"));
  243. }
  244. if (!this.Oneway && !this.Response.IsUntypedMessage)
  245. {
  246. CodeTypeReference typedRespMessageRef = GenerateTypedMessageHeaderAndReturnValueParts(ns, this.DefaultName + "Response", this.Response, true /*isReply*/, hideFromEditor, ref this.IsNewResponse, out this.EndPartCodeGenerator);
  247. this.EndMethod.ReturnType = typedRespMessageRef;
  248. }
  249. GenerateMessageBodyParts(true /*generateTypedMessages*/);
  250. if (!this.IsEncoded)
  251. style = OperationFormatStyle.Document;
  252. }
  253. CodeTypeReference GenerateTypedMessageHeaderAndReturnValueParts(CodeNamespace ns, string defaultName, MessageDescription message, bool isReply, bool hideFromEditor, ref bool isNewMessage, out IPartCodeGenerator partCodeGenerator)
  254. {
  255. CodeTypeReference typedMessageRef;
  256. if (TypedMessageHelper.FindGeneratedTypedMessage(this.Context.Contract, message, out typedMessageRef))
  257. {
  258. partCodeGenerator = null;
  259. isNewMessage = false;
  260. }
  261. else
  262. {
  263. UniqueCodeNamespaceScope namespaceScope = new UniqueCodeNamespaceScope(ns);
  264. CodeTypeDeclaration typedMessageDecl = Context.Contract.TypeFactory.CreateClassType();
  265. string messageName = XmlName.IsNullOrEmpty(message.MessageName) ? null : message.MessageName.DecodedName;
  266. typedMessageRef = namespaceScope.AddUnique(typedMessageDecl, messageName, defaultName);
  267. TypedMessageHelper.AddGeneratedTypedMessage(this.Context.Contract, message, typedMessageRef);
  268. if (this.MessageContractType == MessageContractType.BareMessageContract && message.Body.WrapperName != null)
  269. WrapTypedMessage(ns, typedMessageDecl.Name, message, isReply, this.Context.IsInherited, hideFromEditor);
  270. partCodeGenerator = new TypedMessagePartCodeGenerator(typedMessageDecl);
  271. if (hideFromEditor)
  272. {
  273. TypedMessageHelper.AddEditorBrowsableAttribute(typedMessageDecl.CustomAttributes);
  274. }
  275. TypedMessageHelper.GenerateWrapperAttribute(message, partCodeGenerator);
  276. TypedMessageHelper.GenerateProtectionLevelAttribute(message, partCodeGenerator);
  277. foreach (MessageHeaderDescription setting in message.Headers)
  278. GenerateHeaderPart(setting, partCodeGenerator);
  279. if (isReply && message.Body.ReturnValue != null)
  280. {
  281. GenerateBodyPart(0, message.Body.ReturnValue, partCodeGenerator, true, this.IsEncoded, this.DefaultNS);
  282. }
  283. }
  284. return typedMessageRef;
  285. }
  286. bool IsCompletelyUntyped
  287. {
  288. get
  289. {
  290. bool isRequestMessage = this.Request != null && this.Request.IsUntypedMessage;
  291. bool isResponseMessage = this.Response != null && this.Response.IsUntypedMessage;
  292. if (isRequestMessage && isResponseMessage)
  293. return true;
  294. else if (isResponseMessage && Request == null || IsEmpty(Request))
  295. return true;
  296. else if (isRequestMessage && Response == null || IsEmpty(Response))
  297. return true;
  298. else
  299. return false;
  300. }
  301. }
  302. bool IsEmpty(MessageDescription message)
  303. {
  304. return (message.Body.Parts.Count == 0 && message.Headers.Count == 0);
  305. }
  306. bool HasUntypedMessages
  307. {
  308. get
  309. {
  310. bool isRequestMessage = this.Request != null && this.Request.IsUntypedMessage;
  311. bool isResponseMessage = this.Response != null && this.Response.IsUntypedMessage;
  312. return (isRequestMessage || isResponseMessage);
  313. }
  314. }
  315. void CreateUntypedMessages()
  316. {
  317. bool isRequestMessage = this.Request != null && this.Request.IsUntypedMessage;
  318. bool isResponseMessage = this.Response != null && this.Response.IsUntypedMessage;
  319. if (isRequestMessage)
  320. this.Method.Parameters.Insert(0, new CodeParameterDeclarationExpression(Context.ServiceContractGenerator.GetCodeTypeReference((typeof(Message))), "request"));
  321. if (isResponseMessage)
  322. this.EndMethod.ReturnType = Context.ServiceContractGenerator.GetCodeTypeReference(typeof(Message));
  323. }
  324. void CreateOrOverrideActionProperties()
  325. {
  326. if (this.Request != null)
  327. {
  328. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(
  329. CustomAttributeHelper.FindOrCreateAttributeDeclaration<OperationContractAttribute>(this.Method.CustomAttributes), OperationContractAttribute.ActionPropertyName, this.Request.Action);
  330. }
  331. if (this.Response != null)
  332. {
  333. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(
  334. CustomAttributeHelper.FindOrCreateAttributeDeclaration<OperationContractAttribute>(this.Method.CustomAttributes), OperationContractAttribute.ReplyActionPropertyName, this.Response.Action);
  335. }
  336. }
  337. interface IPartCodeGenerator
  338. {
  339. CodeAttributeDeclarationCollection AddPart(CodeTypeReference type, ref string name);
  340. CodeAttributeDeclarationCollection MessageLevelAttributes { get; }
  341. void EndCodeGeneration();
  342. }
  343. class ParameterizedMethodGenerator
  344. {
  345. ParametersPartCodeGenerator ins;
  346. ParametersPartCodeGenerator outs;
  347. bool isSync;
  348. internal ParameterizedMethodGenerator(CodeMemberMethod beginMethod, CodeMemberMethod endMethod)
  349. {
  350. this.ins = new ParametersPartCodeGenerator(this, beginMethod.Name, beginMethod.Parameters, beginMethod.CustomAttributes, FieldDirection.In);
  351. this.outs = new ParametersPartCodeGenerator(this, beginMethod.Name, endMethod.Parameters, beginMethod.CustomAttributes, FieldDirection.Out);
  352. this.isSync = (beginMethod == endMethod);
  353. }
  354. internal CodeParameterDeclarationExpression GetOrCreateParameter(CodeTypeReference type, string name, FieldDirection direction, ref int index, out bool createdNew)
  355. {
  356. Fx.Assert(System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(name), String.Format(System.Globalization.CultureInfo.InvariantCulture, "Type name '{0}' is not ValidLanguageIndependentIdentifier!", name));
  357. ParametersPartCodeGenerator existingParams = direction != FieldDirection.In ? ins : outs;
  358. int i = index;
  359. CodeParameterDeclarationExpression existing = existingParams.GetParameter(name, ref i);
  360. bool isRef = existing != null && existing.Type.BaseType == type.BaseType;
  361. if (isRef)
  362. {
  363. existing.Direction = FieldDirection.Ref;
  364. if (isSync)
  365. {
  366. index = i + 1;
  367. createdNew = false;
  368. return existing;
  369. }
  370. }
  371. CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression();
  372. paramDecl.Name = name;
  373. paramDecl.Type = type;
  374. paramDecl.Direction = direction;
  375. if (isRef)
  376. paramDecl.Direction = FieldDirection.Ref;
  377. createdNew = true;
  378. return paramDecl;
  379. }
  380. internal IPartCodeGenerator InputGenerator
  381. {
  382. get
  383. {
  384. return this.ins;
  385. }
  386. }
  387. internal IPartCodeGenerator OutputGenerator
  388. {
  389. get
  390. {
  391. return this.outs;
  392. }
  393. }
  394. class ParametersPartCodeGenerator : IPartCodeGenerator
  395. {
  396. ParameterizedMethodGenerator parent;
  397. FieldDirection direction;
  398. CodeParameterDeclarationExpressionCollection parameters;
  399. CodeAttributeDeclarationCollection messageAttrs;
  400. string methodName;
  401. int index;
  402. internal ParametersPartCodeGenerator(ParameterizedMethodGenerator parent, string methodName, CodeParameterDeclarationExpressionCollection parameters, CodeAttributeDeclarationCollection messageAttrs, FieldDirection direction)
  403. {
  404. this.parent = parent;
  405. this.methodName = methodName;
  406. this.parameters = parameters;
  407. this.messageAttrs = messageAttrs;
  408. this.direction = direction;
  409. this.index = 0;
  410. }
  411. public bool NameExists(string name)
  412. {
  413. if (String.Compare(name, methodName, StringComparison.OrdinalIgnoreCase) == 0)
  414. return true;
  415. int index = 0;
  416. return GetParameter(name, ref index) != null;
  417. }
  418. CodeAttributeDeclarationCollection IPartCodeGenerator.AddPart(CodeTypeReference type, ref string name)
  419. {
  420. bool createdNew;
  421. name = UniqueCodeIdentifierScope.MakeValid(name, "param");
  422. CodeParameterDeclarationExpression paramDecl = parent.GetOrCreateParameter(type, name, this.direction, ref index, out createdNew);
  423. if (createdNew)
  424. {
  425. paramDecl.Name = GetUniqueParameterName(paramDecl.Name, this);
  426. parameters.Insert(this.index++, paramDecl);
  427. }
  428. name = paramDecl.Name;
  429. if (!createdNew)
  430. return null;
  431. return paramDecl.CustomAttributes;
  432. }
  433. internal CodeParameterDeclarationExpression GetParameter(string name, ref int index)
  434. {
  435. for (int i = index; i < parameters.Count; i++)
  436. {
  437. CodeParameterDeclarationExpression parameter = parameters[i];
  438. if (String.Compare(parameter.Name, name, StringComparison.OrdinalIgnoreCase) == 0)
  439. {
  440. index = i;
  441. return parameter;
  442. }
  443. }
  444. return null;
  445. }
  446. CodeAttributeDeclarationCollection IPartCodeGenerator.MessageLevelAttributes
  447. {
  448. get
  449. {
  450. return messageAttrs;
  451. }
  452. }
  453. void IPartCodeGenerator.EndCodeGeneration()
  454. {
  455. }
  456. static string GetUniqueParameterName(string name, ParametersPartCodeGenerator parameters)
  457. {
  458. return NamingHelper.GetUniqueName(name, DoesParameterNameExist, parameters);
  459. }
  460. static bool DoesParameterNameExist(string name, object parametersObject)
  461. {
  462. return ((ParametersPartCodeGenerator)parametersObject).NameExists(name);
  463. }
  464. }
  465. }
  466. class TypedMessagePartCodeGenerator : IPartCodeGenerator
  467. {
  468. CodeTypeDeclaration typeDecl;
  469. UniqueCodeIdentifierScope memberScope;
  470. internal TypedMessagePartCodeGenerator(CodeTypeDeclaration typeDecl)
  471. {
  472. this.typeDecl = typeDecl;
  473. this.memberScope = new UniqueCodeIdentifierScope();
  474. this.memberScope.AddReserved(typeDecl.Name);
  475. }
  476. CodeAttributeDeclarationCollection IPartCodeGenerator.AddPart(CodeTypeReference type, ref string name)
  477. {
  478. CodeMemberField memberDecl = new CodeMemberField();
  479. memberDecl.Name = name = this.memberScope.AddUnique(name, "member");
  480. memberDecl.Type = type;
  481. memberDecl.Attributes = MemberAttributes.Public;
  482. typeDecl.Members.Add(memberDecl);
  483. return memberDecl.CustomAttributes;
  484. }
  485. CodeAttributeDeclarationCollection IPartCodeGenerator.MessageLevelAttributes
  486. {
  487. get
  488. {
  489. return typeDecl.CustomAttributes;
  490. }
  491. }
  492. void IPartCodeGenerator.EndCodeGeneration()
  493. {
  494. TypedMessageHelper.GenerateConstructors(typeDecl);
  495. }
  496. }
  497. void WrapTypedMessage(CodeNamespace ns, string typeName, MessageDescription messageDescription, bool isReply, bool isInherited, bool hideFromEditor)
  498. {
  499. Fx.Assert(String.IsNullOrEmpty(typeName) || System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(typeName), String.Format(System.Globalization.CultureInfo.InvariantCulture, "Type name '{0}' is not ValidLanguageIndependentIdentifier!", typeName));
  500. UniqueCodeNamespaceScope namespaceScope = new UniqueCodeNamespaceScope(ns);
  501. CodeTypeDeclaration wrapperTypeDecl = Context.Contract.TypeFactory.CreateClassType();
  502. CodeTypeReference wrapperTypeRef = namespaceScope.AddUnique(wrapperTypeDecl, typeName + "Body", "Body");
  503. if (hideFromEditor)
  504. {
  505. TypedMessageHelper.AddEditorBrowsableAttribute(wrapperTypeDecl.CustomAttributes);
  506. }
  507. string defaultNS = GetWrapperNamespace(messageDescription);
  508. string messageName = XmlName.IsNullOrEmpty(messageDescription.MessageName) ? null : messageDescription.MessageName.DecodedName;
  509. this.WrappedBodyTypeGenerator.AddTypeAttributes(messageName, defaultNS, wrapperTypeDecl.CustomAttributes, this.IsEncoded);
  510. IPartCodeGenerator partGenerator = new TypedMessagePartCodeGenerator(wrapperTypeDecl);
  511. System.Net.Security.ProtectionLevel protectionLevel = System.Net.Security.ProtectionLevel.None;
  512. bool isProtectionLevelSetExplicitly = false;
  513. if (messageDescription.Body.ReturnValue != null)
  514. {
  515. AddWrapperPart(messageDescription.MessageName, this.WrappedBodyTypeGenerator, partGenerator, messageDescription.Body.ReturnValue, wrapperTypeDecl.CustomAttributes);
  516. protectionLevel = ProtectionLevelHelper.Max(protectionLevel, messageDescription.Body.ReturnValue.ProtectionLevel);
  517. if (messageDescription.Body.ReturnValue.HasProtectionLevel)
  518. isProtectionLevelSetExplicitly = true;
  519. }
  520. List<CodeTypeReference> wrapperKnownTypes = new List<CodeTypeReference>();
  521. foreach (MessagePartDescription part in messageDescription.Body.Parts)
  522. {
  523. AddWrapperPart(messageDescription.MessageName, this.WrappedBodyTypeGenerator, partGenerator, part, wrapperTypeDecl.CustomAttributes);
  524. protectionLevel = ProtectionLevelHelper.Max(protectionLevel, part.ProtectionLevel);
  525. if (part.HasProtectionLevel)
  526. isProtectionLevelSetExplicitly = true;
  527. ICollection<CodeTypeReference> knownTypesForPart = null;
  528. if (this.KnownTypes != null && this.KnownTypes.TryGetValue(part, out knownTypesForPart))
  529. {
  530. foreach (CodeTypeReference typeReference in knownTypesForPart)
  531. wrapperKnownTypes.Add(typeReference);
  532. }
  533. }
  534. messageDescription.Body.Parts.Clear();
  535. MessagePartDescription wrapperPart = new MessagePartDescription(messageDescription.Body.WrapperName, messageDescription.Body.WrapperNamespace);
  536. if (this.KnownTypes != null)
  537. this.KnownTypes.Add(wrapperPart, wrapperKnownTypes);
  538. if (isProtectionLevelSetExplicitly)
  539. wrapperPart.ProtectionLevel = protectionLevel;
  540. messageDescription.Body.WrapperName = null;
  541. messageDescription.Body.WrapperNamespace = null;
  542. if (isReply)
  543. messageDescription.Body.ReturnValue = wrapperPart;
  544. else
  545. messageDescription.Body.Parts.Add(wrapperPart);
  546. TypedMessageHelper.GenerateConstructors(wrapperTypeDecl);
  547. this.Parent.ParameterTypes.Add(wrapperPart, wrapperTypeRef);
  548. this.Parent.SpecialPartName.Add(wrapperPart, "Body");
  549. }
  550. string GetWrapperNamespace(MessageDescription messageDescription)
  551. {
  552. string defaultNS = this.DefaultNS;
  553. if (messageDescription.Body.ReturnValue != null)
  554. defaultNS = messageDescription.Body.ReturnValue.Namespace;
  555. else if (messageDescription.Body.Parts.Count > 0)
  556. defaultNS = messageDescription.Body.Parts[0].Namespace;
  557. return defaultNS;
  558. }
  559. void GenerateMessageBodyParts(bool generateTypedMessages)
  560. {
  561. int order = 0;
  562. if (this.IsNewRequest)
  563. {
  564. foreach (MessagePartDescription setting in this.Request.Body.Parts)
  565. GenerateBodyPart(order++, setting, this.BeginPartCodeGenerator, generateTypedMessages, this.IsEncoded, this.DefaultNS);
  566. }
  567. if (!this.Oneway && IsNewResponse)
  568. {
  569. order = this.Response.Body.ReturnValue != null ? 1 : 0;
  570. foreach (MessagePartDescription setting in this.Response.Body.Parts)
  571. GenerateBodyPart(order++, setting, this.EndPartCodeGenerator, generateTypedMessages, this.IsEncoded, this.DefaultNS);
  572. }
  573. if (IsNewRequest)
  574. {
  575. if (this.BeginPartCodeGenerator != null)
  576. this.BeginPartCodeGenerator.EndCodeGeneration();
  577. }
  578. if (IsNewResponse)
  579. {
  580. if (EndPartCodeGenerator != null)
  581. this.EndPartCodeGenerator.EndCodeGeneration();
  582. }
  583. }
  584. void AddWrapperPart(XmlName messageName, IWrappedBodyTypeGenerator wrappedBodyTypeGenerator, IPartCodeGenerator partGenerator, MessagePartDescription part, CodeAttributeDeclarationCollection typeAttributes)
  585. {
  586. string fieldName = part.CodeName;
  587. CodeTypeReference type;
  588. if (part.Type == typeof(System.IO.Stream))
  589. type = Context.ServiceContractGenerator.GetCodeTypeReference(typeof(byte[]));
  590. else
  591. type = GetParameterType(part);
  592. CodeAttributeDeclarationCollection fieldAttributes = partGenerator.AddPart(type, ref fieldName);
  593. CodeAttributeDeclarationCollection importedAttributes = null;
  594. bool hasAttributes = this.Parent.ParameterAttributes.TryGetValue(part, out importedAttributes);
  595. wrappedBodyTypeGenerator.AddMemberAttributes(messageName, part, importedAttributes, typeAttributes, fieldAttributes);
  596. this.Parent.ParameterTypes.Remove(part);
  597. if (hasAttributes)
  598. this.Parent.ParameterAttributes.Remove(part);
  599. }
  600. void GenerateBodyPart(int order, MessagePartDescription messagePart, IPartCodeGenerator partCodeGenerator, bool generateTypedMessage, bool isEncoded, string defaultNS)
  601. {
  602. if (!generateTypedMessage) order = -1;
  603. string partName;
  604. if (!this.Parent.SpecialPartName.TryGetValue(messagePart, out partName))
  605. partName = messagePart.CodeName;
  606. CodeTypeReference partType = GetParameterType(messagePart);
  607. CodeAttributeDeclarationCollection partAttributes = partCodeGenerator.AddPart(partType, ref partName);
  608. if (partAttributes == null)
  609. return;
  610. XmlName xmlPartName = new XmlName(partName);
  611. if (generateTypedMessage)
  612. TypedMessageHelper.GenerateMessageBodyMemberAttribute(order, messagePart, partAttributes, xmlPartName);
  613. else
  614. ParameterizedMessageHelper.GenerateMessageParameterAttribute(messagePart, partAttributes, xmlPartName, defaultNS);
  615. AddAdditionalAttributes(messagePart, partAttributes, generateTypedMessage || isEncoded);
  616. }
  617. void GenerateHeaderPart(MessageHeaderDescription setting, IPartCodeGenerator parts)
  618. {
  619. string partName;
  620. if (!this.Parent.SpecialPartName.TryGetValue(setting, out partName))
  621. partName = setting.CodeName;
  622. CodeTypeReference partType = GetParameterType(setting);
  623. CodeAttributeDeclarationCollection partAttributes = parts.AddPart(partType, ref partName);
  624. TypedMessageHelper.GenerateMessageHeaderAttribute(setting, partAttributes, new XmlName(partName));
  625. AddAdditionalAttributes(setting, partAttributes, true /*isAdditionalAttributesAllowed*/);
  626. }
  627. CodeTypeReference GetParameterType(MessagePartDescription setting)
  628. {
  629. if (setting.Type != null)
  630. return Context.ServiceContractGenerator.GetCodeTypeReference(setting.Type);
  631. else if (this.Parent.parameterTypes.ContainsKey(setting))
  632. return this.Parent.parameterTypes[setting];
  633. else
  634. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxNoTypeSpecifiedForParameter, setting.Name)));
  635. }
  636. void AddAdditionalAttributes(MessagePartDescription setting, CodeAttributeDeclarationCollection attributes, bool isAdditionalAttributesAllowed)
  637. {
  638. if (this.Parent.parameterAttributes != null && this.Parent.parameterAttributes.ContainsKey(setting))
  639. {
  640. CodeAttributeDeclarationCollection localAttributes = this.Parent.parameterAttributes[setting];
  641. if (localAttributes != null && localAttributes.Count > 0)
  642. {
  643. if (isAdditionalAttributesAllowed)
  644. attributes.AddRange(localAttributes);
  645. else
  646. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SfxUseTypedMessageForCustomAttributes, setting.Name, localAttributes[0].AttributeType.BaseType)));
  647. }
  648. }
  649. }
  650. static class TypedMessageHelper
  651. {
  652. internal static void GenerateProtectionLevelAttribute(MessageDescription message, IPartCodeGenerator partCodeGenerator)
  653. {
  654. CodeAttributeDeclaration messageContractAttr = CustomAttributeHelper.FindOrCreateAttributeDeclaration<MessageContractAttribute>(partCodeGenerator.MessageLevelAttributes);
  655. if (message.HasProtectionLevel)
  656. {
  657. messageContractAttr.Arguments.Add(new CodeAttributeArgument("ProtectionLevel",
  658. new CodeFieldReferenceExpression(
  659. new CodeTypeReferenceExpression(typeof(ProtectionLevel)), message.ProtectionLevel.ToString())));
  660. }
  661. }
  662. internal static void GenerateWrapperAttribute(MessageDescription message, IPartCodeGenerator partCodeGenerator)
  663. {
  664. CodeAttributeDeclaration messageContractAttr = CustomAttributeHelper.FindOrCreateAttributeDeclaration<MessageContractAttribute>(partCodeGenerator.MessageLevelAttributes);
  665. if (message.Body.WrapperName != null)
  666. {
  667. // use encoded name to specify exactly what goes on the wire.
  668. messageContractAttr.Arguments.Add(new CodeAttributeArgument("WrapperName",
  669. new CodePrimitiveExpression(NamingHelper.CodeName(message.Body.WrapperName))));
  670. messageContractAttr.Arguments.Add(new CodeAttributeArgument("WrapperNamespace",
  671. new CodePrimitiveExpression(message.Body.WrapperNamespace)));
  672. messageContractAttr.Arguments.Add(new CodeAttributeArgument("IsWrapped",
  673. new CodePrimitiveExpression(true)));
  674. }
  675. else
  676. messageContractAttr.Arguments.Add(new CodeAttributeArgument("IsWrapped",
  677. new CodePrimitiveExpression(false)));
  678. }
  679. internal static void AddEditorBrowsableAttribute(CodeAttributeDeclarationCollection attributes)
  680. {
  681. attributes.Add(ClientClassGenerator.CreateEditorBrowsableAttribute(EditorBrowsableState.Advanced));
  682. }
  683. internal static void AddGeneratedTypedMessage(ServiceContractGenerationContext contract, MessageDescription message, CodeTypeReference codeTypeReference)
  684. {
  685. if (message.XsdTypeName != null && !message.XsdTypeName.IsEmpty)
  686. {
  687. contract.ServiceContractGenerator.GeneratedTypedMessages.Add(message, codeTypeReference);
  688. }
  689. }
  690. internal static bool FindGeneratedTypedMessage(ServiceContractGenerationContext contract, MessageDescription message, out CodeTypeReference codeTypeReference)
  691. {
  692. if (message.XsdTypeName == null || message.XsdTypeName.IsEmpty)
  693. {
  694. codeTypeReference = null;
  695. return false;
  696. }
  697. return contract.ServiceContractGenerator.GeneratedTypedMessages.TryGetValue(message, out codeTypeReference);
  698. }
  699. internal static void GenerateConstructors(CodeTypeDeclaration typeDecl)
  700. {
  701. CodeConstructor defaultCtor = new CodeConstructor();
  702. defaultCtor.Attributes = MemberAttributes.Public;
  703. typeDecl.Members.Add(defaultCtor);
  704. CodeConstructor otherCtor = new CodeConstructor();
  705. otherCtor.Attributes = MemberAttributes.Public;
  706. foreach (CodeTypeMember member in typeDecl.Members)
  707. {
  708. CodeMemberField field = member as CodeMemberField;
  709. if (field == null)
  710. continue;
  711. CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(field.Type, field.Name);
  712. otherCtor.Parameters.Add(param);
  713. otherCtor.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name), new CodeArgumentReferenceExpression(param.Name)));
  714. }
  715. if (otherCtor.Parameters.Count > 0)
  716. typeDecl.Members.Add(otherCtor);
  717. }
  718. internal static void GenerateMessageBodyMemberAttribute(int order, MessagePartDescription setting, CodeAttributeDeclarationCollection attributes, XmlName defaultName)
  719. {
  720. GenerateMessageContractMemberAttribute<MessageBodyMemberAttribute>(order, setting, attributes, defaultName);
  721. }
  722. internal static void GenerateMessageHeaderAttribute(MessageHeaderDescription setting, CodeAttributeDeclarationCollection attributes, XmlName defaultName)
  723. {
  724. if (setting.Multiple)
  725. GenerateMessageContractMemberAttribute<MessageHeaderArrayAttribute>(-1, setting, attributes, defaultName);
  726. else
  727. GenerateMessageContractMemberAttribute<MessageHeaderAttribute>(-1, setting, attributes, defaultName);
  728. }
  729. static void GenerateMessageContractMemberAttribute<T>(int order, MessagePartDescription setting, CodeAttributeDeclarationCollection attrs, XmlName defaultName)
  730. where T : Attribute
  731. {
  732. CodeAttributeDeclaration decl = CustomAttributeHelper.FindOrCreateAttributeDeclaration<T>(attrs);
  733. if (setting.Name != defaultName.EncodedName)
  734. // override name with encoded value specified in wsdl; this only works beacuse
  735. // our Encoding algorithm will leave alredy encoded names untouched
  736. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageContractMemberAttribute.NamePropertyName, setting.Name);
  737. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageContractMemberAttribute.NamespacePropertyName, setting.Namespace);
  738. if (setting.HasProtectionLevel)
  739. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageContractMemberAttribute.ProtectionLevelPropertyName, setting.ProtectionLevel);
  740. if (order >= 0)
  741. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageBodyMemberAttribute.OrderPropertyName, order);
  742. }
  743. }
  744. static class ParameterizedMessageHelper
  745. {
  746. internal static void GenerateMessageParameterAttribute(MessagePartDescription setting, CodeAttributeDeclarationCollection attributes, XmlName defaultName, string defaultNS)
  747. {
  748. if (setting.Name != defaultName.EncodedName)
  749. {
  750. // override name with encoded value specified in wsdl; this only works beacuse
  751. // our Encoding algorithm will leave alredy encoded names untouched
  752. CustomAttributeHelper.CreateOrOverridePropertyDeclaration(
  753. CustomAttributeHelper.FindOrCreateAttributeDeclaration<MessageParameterAttribute>(attributes), MessageParameterAttribute.NamePropertyName, setting.Name);
  754. }
  755. if (setting.Namespace != defaultNS)
  756. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_NamespaceMismatch, setting.Namespace, defaultNS)));
  757. }
  758. internal static void ValidateProtectionLevel(MethodSignatureGenerator parent)
  759. {
  760. if (parent.Request != null && parent.Request.HasProtectionLevel)
  761. {
  762. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_MessageHasProtectionLevel, parent.Request.Action == null ? "" : parent.Request.Action)));
  763. }
  764. if (parent.Response != null && parent.Response.HasProtectionLevel)
  765. {
  766. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_MessageHasProtectionLevel, parent.Response.Action == null ? "" : parent.Response.Action)));
  767. }
  768. }
  769. internal static void ValidateWrapperSettings(MethodSignatureGenerator parent)
  770. {
  771. if (parent.Request.Body.WrapperName == null || (parent.Response != null && parent.Response.Body.WrapperName == null))
  772. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_Bare, parent.Context.Operation.CodeName)));
  773. if (!StringEqualOrNull(parent.Request.Body.WrapperNamespace, parent.ContractNS))
  774. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperNs, parent.Request.MessageName, parent.Request.Body.WrapperNamespace, parent.ContractNS)));
  775. XmlName defaultName = new XmlName(parent.DefaultName);
  776. if (!String.Equals(parent.Request.Body.WrapperName, defaultName.EncodedName, StringComparison.Ordinal))
  777. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperName, parent.Request.MessageName, parent.Request.Body.WrapperName, defaultName.EncodedName)));
  778. if (parent.Response != null)
  779. {
  780. if (!StringEqualOrNull(parent.Response.Body.WrapperNamespace, parent.ContractNS))
  781. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperNs, parent.Response.MessageName, parent.Response.Body.WrapperNamespace, parent.ContractNS)));
  782. if (!String.Equals(parent.Response.Body.WrapperName, TypeLoader.GetBodyWrapperResponseName(defaultName).EncodedName, StringComparison.Ordinal))
  783. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperName, parent.Response.MessageName, parent.Response.Body.WrapperName, defaultName.EncodedName)));
  784. }
  785. }
  786. internal static void ValidateNoHeaders(MethodSignatureGenerator parent)
  787. {
  788. if (parent.Request.Headers.Count > 0)
  789. {
  790. if (parent.IsEncoded)
  791. {
  792. parent.Context.Contract.ServiceContractGenerator.Errors.Add(new MetadataConversionError(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreIgnoredInEncoded, parent.Request.MessageName), true/*isWarning*/));
  793. }
  794. else
  795. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreUnsupported, parent.Request.MessageName)));
  796. }
  797. if (!parent.Oneway && parent.Response.Headers.Count > 0)
  798. {
  799. if (parent.IsEncoded)
  800. parent.Context.Contract.ServiceContractGenerator.Errors.Add(new MetadataConversionError(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreIgnoredInEncoded, parent.Response.MessageName), true/*isWarning*/));
  801. else
  802. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreUnsupported, parent.Response.MessageName)));
  803. }
  804. }
  805. static bool StringEqualOrNull(string overrideValue, string defaultValue)
  806. {
  807. return overrideValue == null || String.Equals(overrideValue, defaultValue, StringComparison.Ordinal);
  808. }
  809. }
  810. internal void GenerateTaskSignature(ref OperationFormatStyle style)
  811. {
  812. this.Method = this.Context.TaskMethod;
  813. this.EndMethod = this.Context.TaskMethod;
  814. this.DefaultName = this.Context.SyncMethod.Name;
  815. GenerateOperationSignatures(ref style);
  816. CodeTypeReference resultType = this.Method.ReturnType;
  817. CodeTypeReference taskReturnType;
  818. if (resultType.BaseType == ServiceReflector.VoidType.FullName)
  819. {
  820. taskReturnType = new CodeTypeReference(ServiceReflector.taskType);
  821. }
  822. else
  823. {
  824. taskReturnType = new CodeTypeReference(this.Context.ServiceContractGenerator.GetCodeTypeReference(ServiceReflector.taskTResultType).BaseType, resultType);
  825. }
  826. this.Method.ReturnType = taskReturnType;
  827. }
  828. }
  829. static class CustomAttributeHelper
  830. {
  831. internal static void CreateOrOverridePropertyDeclaration<V>(CodeAttributeDeclaration attribute, string propertyName, V value)
  832. {
  833. SecurityAttributeGenerationHelper.CreateOrOverridePropertyDeclaration<V>(attribute, propertyName, value);
  834. }
  835. internal static CodeAttributeDeclaration FindOrCreateAttributeDeclaration<T>(CodeAttributeDeclarationCollection attributes)
  836. where T : Attribute
  837. {
  838. return SecurityAttributeGenerationHelper.FindOrCreateAttributeDeclaration<T>(attributes);
  839. }
  840. internal static CodeAttributeDeclaration GenerateAttributeDeclaration(ServiceContractGenerator generator, Attribute attribute)
  841. {
  842. Type attributeType = attribute.GetType();
  843. Attribute defaultAttribute = (Attribute)Activator.CreateInstance(attributeType);
  844. MemberInfo[] publicMembers = attributeType.GetMembers(BindingFlags.Instance | BindingFlags.Public);
  845. Array.Sort<MemberInfo>(publicMembers,
  846. delegate(MemberInfo a, MemberInfo b)
  847. {
  848. return String.Compare(a.Name, b.Name, StringComparison.Ordinal);
  849. }
  850. );
  851. // we should create this reference through ServiceContractGenerator, which tracks referenced assemblies
  852. CodeAttributeDeclaration attr = new CodeAttributeDeclaration(generator.GetCodeTypeReference(attributeType));
  853. foreach (MemberInfo member in publicMembers)
  854. {
  855. if (member.DeclaringType == typeof(Attribute))
  856. continue;
  857. FieldInfo field = member as FieldInfo;
  858. if (field != null)
  859. {
  860. object fieldValue = field.GetValue(attribute);
  861. object defaultValue = field.GetValue(defaultAttribute);
  862. if (!object.Equals(fieldValue, defaultValue))
  863. attr.Arguments.Add(new CodeAttributeArgument(field.Name, GetArgValue(fieldValue)));
  864. continue;
  865. }
  866. PropertyInfo property = member as PropertyInfo;
  867. if (property != null)
  868. {
  869. object propertyValue = property.GetValue(attribute, null);
  870. object defaultValue = property.GetValue(defaultAttribute, null);
  871. if (!object.Equals(propertyValue, defaultValue))
  872. attr.Arguments.Add(new CodeAttributeArgument(property.Name, GetArgValue(propertyValue)));
  873. continue;
  874. }
  875. }
  876. return attr;
  877. }
  878. static CodeExpression GetArgValue(object val)
  879. {
  880. Type type = val.GetType();
  881. if (type.IsPrimitive || type == typeof(string))
  882. return new CodePrimitiveExpression(val);
  883. if (type.IsEnum)
  884. return new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(type), Enum.Format(type, val, "G"));
  885. Fx.Assert(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Attribute generation is not supported for argument type {0}", type));
  886. return null;
  887. }
  888. }
  889. }
  890. class ParameterModeException : Exception
  891. {
  892. MessageContractType messageContractType = MessageContractType.WrappedMessageContract;
  893. public ParameterModeException() { }
  894. public ParameterModeException(string message) : base(message) { }
  895. public ParameterModeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
  896. public MessageContractType MessageContractType
  897. {
  898. get { return messageContractType; }
  899. set { messageContractType = value; }
  900. }
  901. }
  902. }