| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Description
- {
- using System.CodeDom;
- using System.Collections.Generic;
- using System.Net.Security;
- using System.Reflection;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Security;
- using System.ComponentModel;
- using System.Threading.Tasks;
- enum MessageContractType { None, WrappedMessageContract, BareMessageContract }
- interface IWrappedBodyTypeGenerator
- {
- void ValidateForParameterMode(OperationDescription operationDescription);
- void AddMemberAttributes(XmlName messageName, MessagePartDescription part, CodeAttributeDeclarationCollection attributesImported, CodeAttributeDeclarationCollection typeAttributes, CodeAttributeDeclarationCollection fieldAttributes);
- void AddTypeAttributes(string messageName, string typeNS, CodeAttributeDeclarationCollection typeAttributes, bool isEncoded);
- }
- class OperationGenerator //: IOperationBehavior, IOperationContractGenerationExtension
- {
- Dictionary<MessagePartDescription, CodeTypeReference> parameterTypes;
- Dictionary<MessagePartDescription, CodeAttributeDeclarationCollection> parameterAttributes;
- Dictionary<MessagePartDescription, string> specialPartName;
- internal OperationGenerator()
- {
- }
- internal Dictionary<MessagePartDescription, CodeAttributeDeclarationCollection> ParameterAttributes
- {
- get
- {
- if (this.parameterAttributes == null)
- this.parameterAttributes = new Dictionary<MessagePartDescription, CodeAttributeDeclarationCollection>();
- return this.parameterAttributes;
- }
- }
- internal Dictionary<MessagePartDescription, CodeTypeReference> ParameterTypes
- {
- get
- {
- if (this.parameterTypes == null)
- this.parameterTypes = new Dictionary<MessagePartDescription, CodeTypeReference>();
- return this.parameterTypes;
- }
- }
- internal Dictionary<MessagePartDescription, string> SpecialPartName
- {
- get
- {
- if (specialPartName == null)
- this.specialPartName = new Dictionary<MessagePartDescription, string>();
- return specialPartName;
- }
- }
- internal void GenerateOperation(OperationContractGenerationContext context, ref OperationFormatStyle style, bool isEncoded, IWrappedBodyTypeGenerator wrappedBodyTypeGenerator, Dictionary<MessagePartDescription, ICollection<CodeTypeReference>> knownTypes)
- {
- if (context == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("context"));
- if (context.Operation == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.OperationPropertyIsRequiredForAttributeGeneration)));
- MethodSignatureGenerator methodSignatureGenerator = new MethodSignatureGenerator(this, context, style, isEncoded, wrappedBodyTypeGenerator, knownTypes);
- methodSignatureGenerator.GenerateSyncSignature(ref style);
- if (context.IsTask)
- {
- methodSignatureGenerator.GenerateTaskSignature(ref style);
- }
- if (context.IsAsync)
- {
- methodSignatureGenerator.GenerateAsyncSignature(ref style);
- }
- }
- internal static CodeAttributeDeclaration GenerateAttributeDeclaration(ServiceContractGenerator generator, Attribute attribute)
- {
- return CustomAttributeHelper.GenerateAttributeDeclaration(generator, attribute);
- }
- class MethodSignatureGenerator
- {
- readonly OperationGenerator Parent;
- readonly OperationContractGenerationContext Context;
- readonly OperationFormatStyle Style;
- readonly bool IsEncoded;
- readonly IWrappedBodyTypeGenerator WrappedBodyTypeGenerator;
- readonly Dictionary<MessagePartDescription, ICollection<CodeTypeReference>> KnownTypes;
- CodeMemberMethod Method;
- CodeMemberMethod EndMethod;
- readonly string ContractName;
- string DefaultName;
- readonly string ContractNS;
- readonly string DefaultNS;
- readonly bool Oneway;
- readonly MessageDescription Request;
- readonly MessageDescription Response;
- bool IsNewRequest;
- bool IsNewResponse;
- bool IsTaskWithOutputParameters;
- MessageContractType MessageContractType;
- IPartCodeGenerator BeginPartCodeGenerator;
- IPartCodeGenerator EndPartCodeGenerator;
- internal MethodSignatureGenerator(OperationGenerator parent, OperationContractGenerationContext context, OperationFormatStyle style, bool isEncoded, IWrappedBodyTypeGenerator wrappedBodyTypeGenerator, Dictionary<MessagePartDescription, ICollection<CodeTypeReference>> knownTypes)
- {
- this.Parent = parent;
- this.Context = context;
- this.Style = style;
- this.IsEncoded = isEncoded;
- this.WrappedBodyTypeGenerator = wrappedBodyTypeGenerator;
- this.KnownTypes = knownTypes;
- this.MessageContractType = context.ServiceContractGenerator.OptionsInternal.IsSet(ServiceContractGenerationOptions.TypedMessages) ? MessageContractType.WrappedMessageContract : MessageContractType.None;
- this.ContractName = context.Contract.Contract.CodeName;
- this.ContractNS = context.Operation.DeclaringContract.Namespace;
- this.DefaultNS = (style == OperationFormatStyle.Rpc) ? string.Empty : this.ContractNS;
- this.Oneway = (context.Operation.IsOneWay);
- this.Request = context.Operation.Messages[0];
- this.Response = this.Oneway ? null : context.Operation.Messages[1];
- this.IsNewRequest = true;
- this.IsNewResponse = true;
- this.BeginPartCodeGenerator = null;
- this.EndPartCodeGenerator = null;
- this.IsTaskWithOutputParameters = context.IsTask && context.Operation.HasOutputParameters;
- Fx.Assert(this.Oneway == (this.Response == null), "OperationContractGenerationContext.Operation cannot contain a null response message when the operation is not one-way");
- }
- internal void GenerateSyncSignature(ref OperationFormatStyle style)
- {
- this.Method = this.Context.SyncMethod;
- this.EndMethod = this.Context.SyncMethod;
- this.DefaultName = this.Method.Name;
- GenerateOperationSignatures(ref style);
- }
- internal void GenerateAsyncSignature(ref OperationFormatStyle style)
- {
- this.Method = this.Context.BeginMethod;
- this.EndMethod = this.Context.EndMethod;
- this.DefaultName = this.Method.Name.Substring(5);
- GenerateOperationSignatures(ref style);
- }
- void GenerateOperationSignatures(ref OperationFormatStyle style)
- {
- if (this.MessageContractType != MessageContractType.None || this.GenerateTypedMessageForTaskWithOutputParameters())
- {
- CheckAndSetMessageContractTypeToBare();
- this.GenerateTypedMessageOperation(false /*hideFromEditor*/, ref style);
- }
- else if (!this.TryGenerateParameterizedOperation())
- {
- this.GenerateTypedMessageOperation(true /*hideFromEditor*/, ref style);
- }
- }
- bool GenerateTypedMessageForTaskWithOutputParameters()
- {
- if (this.IsTaskWithOutputParameters)
- {
- if (this.Method == this.Context.TaskMethod)
- {
- this.Method.Comments.Add(new CodeCommentStatement(SR.GetString(SR.SFxCodeGenWarning, SR.GetString(SR.SFxCannotImportAsParameters_OutputParameterAndTask))));
- }
-
- return true;
- }
- return false;
- }
- void CheckAndSetMessageContractTypeToBare()
- {
- if (this.MessageContractType == MessageContractType.BareMessageContract)
- return;
- try
- {
- this.WrappedBodyTypeGenerator.ValidateForParameterMode(this.Context.Operation);
- }
- catch (ParameterModeException ex)
- {
- this.MessageContractType = ex.MessageContractType;
- }
- }
- bool TryGenerateParameterizedOperation()
- {
- CodeParameterDeclarationExpressionCollection methodParameters, endMethodParameters = null;
- methodParameters = new CodeParameterDeclarationExpressionCollection(this.Method.Parameters);
- if (this.EndMethod != null)
- endMethodParameters = new CodeParameterDeclarationExpressionCollection(this.EndMethod.Parameters);
- try
- {
- GenerateParameterizedOperation();
- }
- catch (ParameterModeException ex)
- {
- this.MessageContractType = ex.MessageContractType;
- CodeMemberMethod method = this.Method;
- method.Comments.Add(new CodeCommentStatement(SR.GetString(SR.SFxCodeGenWarning, ex.Message)));
- method.Parameters.Clear();
- method.Parameters.AddRange(methodParameters);
- if (this.Context.IsAsync)
- {
- CodeMemberMethod endMethod = this.EndMethod;
- endMethod.Parameters.Clear();
- endMethod.Parameters.AddRange(endMethodParameters);
- }
- return false;
- }
- return true;
- }
- void GenerateParameterizedOperation()
- {
- ParameterizedMessageHelper.ValidateProtectionLevel(this);
- CreateOrOverrideActionProperties();
- if (this.HasUntypedMessages)
- {
- if (!this.IsCompletelyUntyped)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_Message, this.Context.Operation.CodeName)));
- CreateUntypedMessages();
- }
- else
- {
- ParameterizedMessageHelper.ValidateWrapperSettings(this);
- ParameterizedMessageHelper.ValidateNoHeaders(this);
- this.WrappedBodyTypeGenerator.ValidateForParameterMode(this.Context.Operation);
- ParameterizedMethodGenerator generator = new ParameterizedMethodGenerator(this.Method, this.EndMethod);
- this.BeginPartCodeGenerator = generator.InputGenerator;
- this.EndPartCodeGenerator = generator.OutputGenerator;
- if (!this.Oneway && this.Response.Body.ReturnValue != null)
- {
- this.EndMethod.ReturnType = GetParameterType(this.Response.Body.ReturnValue);
- ParameterizedMessageHelper.GenerateMessageParameterAttribute(this.Response.Body.ReturnValue, this.EndMethod.ReturnTypeCustomAttributes, TypeLoader.GetReturnValueName(this.DefaultName), this.DefaultNS);
- AddAdditionalAttributes(this.Response.Body.ReturnValue, this.EndMethod.ReturnTypeCustomAttributes, this.IsEncoded);
- }
- GenerateMessageBodyParts(false /*generateTypedMessages*/);
- }
- }
- void GenerateTypedMessageOperation(bool hideFromEditor, ref OperationFormatStyle style)
- {
- CreateOrOverrideActionProperties();
- if (this.HasUntypedMessages)
- {
- CreateUntypedMessages();
- if (this.IsCompletelyUntyped)
- return;
- }
- CodeNamespace ns = this.Context.ServiceContractGenerator.NamespaceManager.EnsureNamespace(this.ContractNS);
- if (!this.Request.IsUntypedMessage)
- {
- CodeTypeReference typedReqMessageRef = GenerateTypedMessageHeaderAndReturnValueParts(ns, this.DefaultName + "Request", this.Request, false /*isReply*/, hideFromEditor, ref this.IsNewRequest, out this.BeginPartCodeGenerator);
- this.Method.Parameters.Insert(0, new CodeParameterDeclarationExpression(typedReqMessageRef, "request"));
- }
- if (!this.Oneway && !this.Response.IsUntypedMessage)
- {
- CodeTypeReference typedRespMessageRef = GenerateTypedMessageHeaderAndReturnValueParts(ns, this.DefaultName + "Response", this.Response, true /*isReply*/, hideFromEditor, ref this.IsNewResponse, out this.EndPartCodeGenerator);
- this.EndMethod.ReturnType = typedRespMessageRef;
- }
- GenerateMessageBodyParts(true /*generateTypedMessages*/);
- if (!this.IsEncoded)
- style = OperationFormatStyle.Document;
- }
- CodeTypeReference GenerateTypedMessageHeaderAndReturnValueParts(CodeNamespace ns, string defaultName, MessageDescription message, bool isReply, bool hideFromEditor, ref bool isNewMessage, out IPartCodeGenerator partCodeGenerator)
- {
- CodeTypeReference typedMessageRef;
- if (TypedMessageHelper.FindGeneratedTypedMessage(this.Context.Contract, message, out typedMessageRef))
- {
- partCodeGenerator = null;
- isNewMessage = false;
- }
- else
- {
- UniqueCodeNamespaceScope namespaceScope = new UniqueCodeNamespaceScope(ns);
- CodeTypeDeclaration typedMessageDecl = Context.Contract.TypeFactory.CreateClassType();
- string messageName = XmlName.IsNullOrEmpty(message.MessageName) ? null : message.MessageName.DecodedName;
- typedMessageRef = namespaceScope.AddUnique(typedMessageDecl, messageName, defaultName);
- TypedMessageHelper.AddGeneratedTypedMessage(this.Context.Contract, message, typedMessageRef);
- if (this.MessageContractType == MessageContractType.BareMessageContract && message.Body.WrapperName != null)
- WrapTypedMessage(ns, typedMessageDecl.Name, message, isReply, this.Context.IsInherited, hideFromEditor);
- partCodeGenerator = new TypedMessagePartCodeGenerator(typedMessageDecl);
- if (hideFromEditor)
- {
- TypedMessageHelper.AddEditorBrowsableAttribute(typedMessageDecl.CustomAttributes);
- }
- TypedMessageHelper.GenerateWrapperAttribute(message, partCodeGenerator);
- TypedMessageHelper.GenerateProtectionLevelAttribute(message, partCodeGenerator);
- foreach (MessageHeaderDescription setting in message.Headers)
- GenerateHeaderPart(setting, partCodeGenerator);
- if (isReply && message.Body.ReturnValue != null)
- {
- GenerateBodyPart(0, message.Body.ReturnValue, partCodeGenerator, true, this.IsEncoded, this.DefaultNS);
- }
- }
- return typedMessageRef;
- }
- bool IsCompletelyUntyped
- {
- get
- {
- bool isRequestMessage = this.Request != null && this.Request.IsUntypedMessage;
- bool isResponseMessage = this.Response != null && this.Response.IsUntypedMessage;
- if (isRequestMessage && isResponseMessage)
- return true;
- else if (isResponseMessage && Request == null || IsEmpty(Request))
- return true;
- else if (isRequestMessage && Response == null || IsEmpty(Response))
- return true;
- else
- return false;
- }
- }
- bool IsEmpty(MessageDescription message)
- {
- return (message.Body.Parts.Count == 0 && message.Headers.Count == 0);
- }
- bool HasUntypedMessages
- {
- get
- {
- bool isRequestMessage = this.Request != null && this.Request.IsUntypedMessage;
- bool isResponseMessage = this.Response != null && this.Response.IsUntypedMessage;
- return (isRequestMessage || isResponseMessage);
- }
- }
- void CreateUntypedMessages()
- {
- bool isRequestMessage = this.Request != null && this.Request.IsUntypedMessage;
- bool isResponseMessage = this.Response != null && this.Response.IsUntypedMessage;
- if (isRequestMessage)
- this.Method.Parameters.Insert(0, new CodeParameterDeclarationExpression(Context.ServiceContractGenerator.GetCodeTypeReference((typeof(Message))), "request"));
- if (isResponseMessage)
- this.EndMethod.ReturnType = Context.ServiceContractGenerator.GetCodeTypeReference(typeof(Message));
- }
- void CreateOrOverrideActionProperties()
- {
- if (this.Request != null)
- {
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(
- CustomAttributeHelper.FindOrCreateAttributeDeclaration<OperationContractAttribute>(this.Method.CustomAttributes), OperationContractAttribute.ActionPropertyName, this.Request.Action);
- }
- if (this.Response != null)
- {
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(
- CustomAttributeHelper.FindOrCreateAttributeDeclaration<OperationContractAttribute>(this.Method.CustomAttributes), OperationContractAttribute.ReplyActionPropertyName, this.Response.Action);
- }
- }
- interface IPartCodeGenerator
- {
- CodeAttributeDeclarationCollection AddPart(CodeTypeReference type, ref string name);
- CodeAttributeDeclarationCollection MessageLevelAttributes { get; }
- void EndCodeGeneration();
- }
- class ParameterizedMethodGenerator
- {
- ParametersPartCodeGenerator ins;
- ParametersPartCodeGenerator outs;
- bool isSync;
- internal ParameterizedMethodGenerator(CodeMemberMethod beginMethod, CodeMemberMethod endMethod)
- {
- this.ins = new ParametersPartCodeGenerator(this, beginMethod.Name, beginMethod.Parameters, beginMethod.CustomAttributes, FieldDirection.In);
- this.outs = new ParametersPartCodeGenerator(this, beginMethod.Name, endMethod.Parameters, beginMethod.CustomAttributes, FieldDirection.Out);
- this.isSync = (beginMethod == endMethod);
- }
- internal CodeParameterDeclarationExpression GetOrCreateParameter(CodeTypeReference type, string name, FieldDirection direction, ref int index, out bool createdNew)
- {
- Fx.Assert(System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(name), String.Format(System.Globalization.CultureInfo.InvariantCulture, "Type name '{0}' is not ValidLanguageIndependentIdentifier!", name));
- ParametersPartCodeGenerator existingParams = direction != FieldDirection.In ? ins : outs;
- int i = index;
- CodeParameterDeclarationExpression existing = existingParams.GetParameter(name, ref i);
- bool isRef = existing != null && existing.Type.BaseType == type.BaseType;
- if (isRef)
- {
- existing.Direction = FieldDirection.Ref;
- if (isSync)
- {
- index = i + 1;
- createdNew = false;
- return existing;
- }
- }
- CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression();
- paramDecl.Name = name;
- paramDecl.Type = type;
- paramDecl.Direction = direction;
- if (isRef)
- paramDecl.Direction = FieldDirection.Ref;
- createdNew = true;
- return paramDecl;
- }
- internal IPartCodeGenerator InputGenerator
- {
- get
- {
- return this.ins;
- }
- }
- internal IPartCodeGenerator OutputGenerator
- {
- get
- {
- return this.outs;
- }
- }
- class ParametersPartCodeGenerator : IPartCodeGenerator
- {
- ParameterizedMethodGenerator parent;
- FieldDirection direction;
- CodeParameterDeclarationExpressionCollection parameters;
- CodeAttributeDeclarationCollection messageAttrs;
- string methodName;
- int index;
- internal ParametersPartCodeGenerator(ParameterizedMethodGenerator parent, string methodName, CodeParameterDeclarationExpressionCollection parameters, CodeAttributeDeclarationCollection messageAttrs, FieldDirection direction)
- {
- this.parent = parent;
- this.methodName = methodName;
- this.parameters = parameters;
- this.messageAttrs = messageAttrs;
- this.direction = direction;
- this.index = 0;
- }
- public bool NameExists(string name)
- {
- if (String.Compare(name, methodName, StringComparison.OrdinalIgnoreCase) == 0)
- return true;
- int index = 0;
- return GetParameter(name, ref index) != null;
- }
- CodeAttributeDeclarationCollection IPartCodeGenerator.AddPart(CodeTypeReference type, ref string name)
- {
- bool createdNew;
- name = UniqueCodeIdentifierScope.MakeValid(name, "param");
- CodeParameterDeclarationExpression paramDecl = parent.GetOrCreateParameter(type, name, this.direction, ref index, out createdNew);
- if (createdNew)
- {
- paramDecl.Name = GetUniqueParameterName(paramDecl.Name, this);
- parameters.Insert(this.index++, paramDecl);
- }
- name = paramDecl.Name;
- if (!createdNew)
- return null;
- return paramDecl.CustomAttributes;
- }
- internal CodeParameterDeclarationExpression GetParameter(string name, ref int index)
- {
- for (int i = index; i < parameters.Count; i++)
- {
- CodeParameterDeclarationExpression parameter = parameters[i];
- if (String.Compare(parameter.Name, name, StringComparison.OrdinalIgnoreCase) == 0)
- {
- index = i;
- return parameter;
- }
- }
- return null;
- }
- CodeAttributeDeclarationCollection IPartCodeGenerator.MessageLevelAttributes
- {
- get
- {
- return messageAttrs;
- }
- }
- void IPartCodeGenerator.EndCodeGeneration()
- {
- }
- static string GetUniqueParameterName(string name, ParametersPartCodeGenerator parameters)
- {
- return NamingHelper.GetUniqueName(name, DoesParameterNameExist, parameters);
- }
- static bool DoesParameterNameExist(string name, object parametersObject)
- {
- return ((ParametersPartCodeGenerator)parametersObject).NameExists(name);
- }
- }
- }
- class TypedMessagePartCodeGenerator : IPartCodeGenerator
- {
- CodeTypeDeclaration typeDecl;
- UniqueCodeIdentifierScope memberScope;
- internal TypedMessagePartCodeGenerator(CodeTypeDeclaration typeDecl)
- {
- this.typeDecl = typeDecl;
- this.memberScope = new UniqueCodeIdentifierScope();
- this.memberScope.AddReserved(typeDecl.Name);
- }
- CodeAttributeDeclarationCollection IPartCodeGenerator.AddPart(CodeTypeReference type, ref string name)
- {
- CodeMemberField memberDecl = new CodeMemberField();
- memberDecl.Name = name = this.memberScope.AddUnique(name, "member");
- memberDecl.Type = type;
- memberDecl.Attributes = MemberAttributes.Public;
- typeDecl.Members.Add(memberDecl);
- return memberDecl.CustomAttributes;
- }
- CodeAttributeDeclarationCollection IPartCodeGenerator.MessageLevelAttributes
- {
- get
- {
- return typeDecl.CustomAttributes;
- }
- }
- void IPartCodeGenerator.EndCodeGeneration()
- {
- TypedMessageHelper.GenerateConstructors(typeDecl);
- }
- }
- void WrapTypedMessage(CodeNamespace ns, string typeName, MessageDescription messageDescription, bool isReply, bool isInherited, bool hideFromEditor)
- {
- Fx.Assert(String.IsNullOrEmpty(typeName) || System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(typeName), String.Format(System.Globalization.CultureInfo.InvariantCulture, "Type name '{0}' is not ValidLanguageIndependentIdentifier!", typeName));
- UniqueCodeNamespaceScope namespaceScope = new UniqueCodeNamespaceScope(ns);
- CodeTypeDeclaration wrapperTypeDecl = Context.Contract.TypeFactory.CreateClassType();
- CodeTypeReference wrapperTypeRef = namespaceScope.AddUnique(wrapperTypeDecl, typeName + "Body", "Body");
- if (hideFromEditor)
- {
- TypedMessageHelper.AddEditorBrowsableAttribute(wrapperTypeDecl.CustomAttributes);
- }
- string defaultNS = GetWrapperNamespace(messageDescription);
- string messageName = XmlName.IsNullOrEmpty(messageDescription.MessageName) ? null : messageDescription.MessageName.DecodedName;
- this.WrappedBodyTypeGenerator.AddTypeAttributes(messageName, defaultNS, wrapperTypeDecl.CustomAttributes, this.IsEncoded);
- IPartCodeGenerator partGenerator = new TypedMessagePartCodeGenerator(wrapperTypeDecl);
- System.Net.Security.ProtectionLevel protectionLevel = System.Net.Security.ProtectionLevel.None;
- bool isProtectionLevelSetExplicitly = false;
- if (messageDescription.Body.ReturnValue != null)
- {
- AddWrapperPart(messageDescription.MessageName, this.WrappedBodyTypeGenerator, partGenerator, messageDescription.Body.ReturnValue, wrapperTypeDecl.CustomAttributes);
- protectionLevel = ProtectionLevelHelper.Max(protectionLevel, messageDescription.Body.ReturnValue.ProtectionLevel);
- if (messageDescription.Body.ReturnValue.HasProtectionLevel)
- isProtectionLevelSetExplicitly = true;
- }
- List<CodeTypeReference> wrapperKnownTypes = new List<CodeTypeReference>();
- foreach (MessagePartDescription part in messageDescription.Body.Parts)
- {
- AddWrapperPart(messageDescription.MessageName, this.WrappedBodyTypeGenerator, partGenerator, part, wrapperTypeDecl.CustomAttributes);
- protectionLevel = ProtectionLevelHelper.Max(protectionLevel, part.ProtectionLevel);
- if (part.HasProtectionLevel)
- isProtectionLevelSetExplicitly = true;
- ICollection<CodeTypeReference> knownTypesForPart = null;
- if (this.KnownTypes != null && this.KnownTypes.TryGetValue(part, out knownTypesForPart))
- {
- foreach (CodeTypeReference typeReference in knownTypesForPart)
- wrapperKnownTypes.Add(typeReference);
- }
- }
- messageDescription.Body.Parts.Clear();
- MessagePartDescription wrapperPart = new MessagePartDescription(messageDescription.Body.WrapperName, messageDescription.Body.WrapperNamespace);
- if (this.KnownTypes != null)
- this.KnownTypes.Add(wrapperPart, wrapperKnownTypes);
- if (isProtectionLevelSetExplicitly)
- wrapperPart.ProtectionLevel = protectionLevel;
- messageDescription.Body.WrapperName = null;
- messageDescription.Body.WrapperNamespace = null;
- if (isReply)
- messageDescription.Body.ReturnValue = wrapperPart;
- else
- messageDescription.Body.Parts.Add(wrapperPart);
- TypedMessageHelper.GenerateConstructors(wrapperTypeDecl);
- this.Parent.ParameterTypes.Add(wrapperPart, wrapperTypeRef);
- this.Parent.SpecialPartName.Add(wrapperPart, "Body");
- }
- string GetWrapperNamespace(MessageDescription messageDescription)
- {
- string defaultNS = this.DefaultNS;
- if (messageDescription.Body.ReturnValue != null)
- defaultNS = messageDescription.Body.ReturnValue.Namespace;
- else if (messageDescription.Body.Parts.Count > 0)
- defaultNS = messageDescription.Body.Parts[0].Namespace;
- return defaultNS;
- }
- void GenerateMessageBodyParts(bool generateTypedMessages)
- {
- int order = 0;
- if (this.IsNewRequest)
- {
- foreach (MessagePartDescription setting in this.Request.Body.Parts)
- GenerateBodyPart(order++, setting, this.BeginPartCodeGenerator, generateTypedMessages, this.IsEncoded, this.DefaultNS);
- }
- if (!this.Oneway && IsNewResponse)
- {
- order = this.Response.Body.ReturnValue != null ? 1 : 0;
- foreach (MessagePartDescription setting in this.Response.Body.Parts)
- GenerateBodyPart(order++, setting, this.EndPartCodeGenerator, generateTypedMessages, this.IsEncoded, this.DefaultNS);
- }
- if (IsNewRequest)
- {
- if (this.BeginPartCodeGenerator != null)
- this.BeginPartCodeGenerator.EndCodeGeneration();
- }
- if (IsNewResponse)
- {
- if (EndPartCodeGenerator != null)
- this.EndPartCodeGenerator.EndCodeGeneration();
- }
- }
- void AddWrapperPart(XmlName messageName, IWrappedBodyTypeGenerator wrappedBodyTypeGenerator, IPartCodeGenerator partGenerator, MessagePartDescription part, CodeAttributeDeclarationCollection typeAttributes)
- {
- string fieldName = part.CodeName;
- CodeTypeReference type;
- if (part.Type == typeof(System.IO.Stream))
- type = Context.ServiceContractGenerator.GetCodeTypeReference(typeof(byte[]));
- else
- type = GetParameterType(part);
- CodeAttributeDeclarationCollection fieldAttributes = partGenerator.AddPart(type, ref fieldName);
- CodeAttributeDeclarationCollection importedAttributes = null;
- bool hasAttributes = this.Parent.ParameterAttributes.TryGetValue(part, out importedAttributes);
- wrappedBodyTypeGenerator.AddMemberAttributes(messageName, part, importedAttributes, typeAttributes, fieldAttributes);
- this.Parent.ParameterTypes.Remove(part);
- if (hasAttributes)
- this.Parent.ParameterAttributes.Remove(part);
- }
- void GenerateBodyPart(int order, MessagePartDescription messagePart, IPartCodeGenerator partCodeGenerator, bool generateTypedMessage, bool isEncoded, string defaultNS)
- {
- if (!generateTypedMessage) order = -1;
- string partName;
- if (!this.Parent.SpecialPartName.TryGetValue(messagePart, out partName))
- partName = messagePart.CodeName;
- CodeTypeReference partType = GetParameterType(messagePart);
- CodeAttributeDeclarationCollection partAttributes = partCodeGenerator.AddPart(partType, ref partName);
- if (partAttributes == null)
- return;
- XmlName xmlPartName = new XmlName(partName);
- if (generateTypedMessage)
- TypedMessageHelper.GenerateMessageBodyMemberAttribute(order, messagePart, partAttributes, xmlPartName);
- else
- ParameterizedMessageHelper.GenerateMessageParameterAttribute(messagePart, partAttributes, xmlPartName, defaultNS);
- AddAdditionalAttributes(messagePart, partAttributes, generateTypedMessage || isEncoded);
- }
- void GenerateHeaderPart(MessageHeaderDescription setting, IPartCodeGenerator parts)
- {
- string partName;
- if (!this.Parent.SpecialPartName.TryGetValue(setting, out partName))
- partName = setting.CodeName;
- CodeTypeReference partType = GetParameterType(setting);
- CodeAttributeDeclarationCollection partAttributes = parts.AddPart(partType, ref partName);
- TypedMessageHelper.GenerateMessageHeaderAttribute(setting, partAttributes, new XmlName(partName));
- AddAdditionalAttributes(setting, partAttributes, true /*isAdditionalAttributesAllowed*/);
- }
- CodeTypeReference GetParameterType(MessagePartDescription setting)
- {
- if (setting.Type != null)
- return Context.ServiceContractGenerator.GetCodeTypeReference(setting.Type);
- else if (this.Parent.parameterTypes.ContainsKey(setting))
- return this.Parent.parameterTypes[setting];
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxNoTypeSpecifiedForParameter, setting.Name)));
- }
- void AddAdditionalAttributes(MessagePartDescription setting, CodeAttributeDeclarationCollection attributes, bool isAdditionalAttributesAllowed)
- {
- if (this.Parent.parameterAttributes != null && this.Parent.parameterAttributes.ContainsKey(setting))
- {
- CodeAttributeDeclarationCollection localAttributes = this.Parent.parameterAttributes[setting];
- if (localAttributes != null && localAttributes.Count > 0)
- {
- if (isAdditionalAttributesAllowed)
- attributes.AddRange(localAttributes);
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SfxUseTypedMessageForCustomAttributes, setting.Name, localAttributes[0].AttributeType.BaseType)));
- }
- }
- }
- static class TypedMessageHelper
- {
- internal static void GenerateProtectionLevelAttribute(MessageDescription message, IPartCodeGenerator partCodeGenerator)
- {
- CodeAttributeDeclaration messageContractAttr = CustomAttributeHelper.FindOrCreateAttributeDeclaration<MessageContractAttribute>(partCodeGenerator.MessageLevelAttributes);
- if (message.HasProtectionLevel)
- {
- messageContractAttr.Arguments.Add(new CodeAttributeArgument("ProtectionLevel",
- new CodeFieldReferenceExpression(
- new CodeTypeReferenceExpression(typeof(ProtectionLevel)), message.ProtectionLevel.ToString())));
- }
- }
- internal static void GenerateWrapperAttribute(MessageDescription message, IPartCodeGenerator partCodeGenerator)
- {
- CodeAttributeDeclaration messageContractAttr = CustomAttributeHelper.FindOrCreateAttributeDeclaration<MessageContractAttribute>(partCodeGenerator.MessageLevelAttributes);
- if (message.Body.WrapperName != null)
- {
- // use encoded name to specify exactly what goes on the wire.
- messageContractAttr.Arguments.Add(new CodeAttributeArgument("WrapperName",
- new CodePrimitiveExpression(NamingHelper.CodeName(message.Body.WrapperName))));
- messageContractAttr.Arguments.Add(new CodeAttributeArgument("WrapperNamespace",
- new CodePrimitiveExpression(message.Body.WrapperNamespace)));
- messageContractAttr.Arguments.Add(new CodeAttributeArgument("IsWrapped",
- new CodePrimitiveExpression(true)));
- }
- else
- messageContractAttr.Arguments.Add(new CodeAttributeArgument("IsWrapped",
- new CodePrimitiveExpression(false)));
- }
- internal static void AddEditorBrowsableAttribute(CodeAttributeDeclarationCollection attributes)
- {
- attributes.Add(ClientClassGenerator.CreateEditorBrowsableAttribute(EditorBrowsableState.Advanced));
- }
- internal static void AddGeneratedTypedMessage(ServiceContractGenerationContext contract, MessageDescription message, CodeTypeReference codeTypeReference)
- {
- if (message.XsdTypeName != null && !message.XsdTypeName.IsEmpty)
- {
- contract.ServiceContractGenerator.GeneratedTypedMessages.Add(message, codeTypeReference);
- }
- }
- internal static bool FindGeneratedTypedMessage(ServiceContractGenerationContext contract, MessageDescription message, out CodeTypeReference codeTypeReference)
- {
- if (message.XsdTypeName == null || message.XsdTypeName.IsEmpty)
- {
- codeTypeReference = null;
- return false;
- }
- return contract.ServiceContractGenerator.GeneratedTypedMessages.TryGetValue(message, out codeTypeReference);
- }
- internal static void GenerateConstructors(CodeTypeDeclaration typeDecl)
- {
- CodeConstructor defaultCtor = new CodeConstructor();
- defaultCtor.Attributes = MemberAttributes.Public;
- typeDecl.Members.Add(defaultCtor);
- CodeConstructor otherCtor = new CodeConstructor();
- otherCtor.Attributes = MemberAttributes.Public;
- foreach (CodeTypeMember member in typeDecl.Members)
- {
- CodeMemberField field = member as CodeMemberField;
- if (field == null)
- continue;
- CodeParameterDeclarationExpression param = new CodeParameterDeclarationExpression(field.Type, field.Name);
- otherCtor.Parameters.Add(param);
- otherCtor.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name), new CodeArgumentReferenceExpression(param.Name)));
- }
- if (otherCtor.Parameters.Count > 0)
- typeDecl.Members.Add(otherCtor);
- }
- internal static void GenerateMessageBodyMemberAttribute(int order, MessagePartDescription setting, CodeAttributeDeclarationCollection attributes, XmlName defaultName)
- {
- GenerateMessageContractMemberAttribute<MessageBodyMemberAttribute>(order, setting, attributes, defaultName);
- }
- internal static void GenerateMessageHeaderAttribute(MessageHeaderDescription setting, CodeAttributeDeclarationCollection attributes, XmlName defaultName)
- {
- if (setting.Multiple)
- GenerateMessageContractMemberAttribute<MessageHeaderArrayAttribute>(-1, setting, attributes, defaultName);
- else
- GenerateMessageContractMemberAttribute<MessageHeaderAttribute>(-1, setting, attributes, defaultName);
- }
- static void GenerateMessageContractMemberAttribute<T>(int order, MessagePartDescription setting, CodeAttributeDeclarationCollection attrs, XmlName defaultName)
- where T : Attribute
- {
- CodeAttributeDeclaration decl = CustomAttributeHelper.FindOrCreateAttributeDeclaration<T>(attrs);
- if (setting.Name != defaultName.EncodedName)
- // override name with encoded value specified in wsdl; this only works beacuse
- // our Encoding algorithm will leave alredy encoded names untouched
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageContractMemberAttribute.NamePropertyName, setting.Name);
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageContractMemberAttribute.NamespacePropertyName, setting.Namespace);
- if (setting.HasProtectionLevel)
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageContractMemberAttribute.ProtectionLevelPropertyName, setting.ProtectionLevel);
- if (order >= 0)
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(decl, MessageBodyMemberAttribute.OrderPropertyName, order);
- }
- }
- static class ParameterizedMessageHelper
- {
- internal static void GenerateMessageParameterAttribute(MessagePartDescription setting, CodeAttributeDeclarationCollection attributes, XmlName defaultName, string defaultNS)
- {
- if (setting.Name != defaultName.EncodedName)
- {
- // override name with encoded value specified in wsdl; this only works beacuse
- // our Encoding algorithm will leave alredy encoded names untouched
- CustomAttributeHelper.CreateOrOverridePropertyDeclaration(
- CustomAttributeHelper.FindOrCreateAttributeDeclaration<MessageParameterAttribute>(attributes), MessageParameterAttribute.NamePropertyName, setting.Name);
- }
- if (setting.Namespace != defaultNS)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_NamespaceMismatch, setting.Namespace, defaultNS)));
- }
- internal static void ValidateProtectionLevel(MethodSignatureGenerator parent)
- {
- if (parent.Request != null && parent.Request.HasProtectionLevel)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_MessageHasProtectionLevel, parent.Request.Action == null ? "" : parent.Request.Action)));
- }
- if (parent.Response != null && parent.Response.HasProtectionLevel)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_MessageHasProtectionLevel, parent.Response.Action == null ? "" : parent.Response.Action)));
- }
- }
- internal static void ValidateWrapperSettings(MethodSignatureGenerator parent)
- {
- if (parent.Request.Body.WrapperName == null || (parent.Response != null && parent.Response.Body.WrapperName == null))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_Bare, parent.Context.Operation.CodeName)));
- if (!StringEqualOrNull(parent.Request.Body.WrapperNamespace, parent.ContractNS))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperNs, parent.Request.MessageName, parent.Request.Body.WrapperNamespace, parent.ContractNS)));
- XmlName defaultName = new XmlName(parent.DefaultName);
- if (!String.Equals(parent.Request.Body.WrapperName, defaultName.EncodedName, StringComparison.Ordinal))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperName, parent.Request.MessageName, parent.Request.Body.WrapperName, defaultName.EncodedName)));
- if (parent.Response != null)
- {
- if (!StringEqualOrNull(parent.Response.Body.WrapperNamespace, parent.ContractNS))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperNs, parent.Response.MessageName, parent.Response.Body.WrapperNamespace, parent.ContractNS)));
- if (!String.Equals(parent.Response.Body.WrapperName, TypeLoader.GetBodyWrapperResponseName(defaultName).EncodedName, StringComparison.Ordinal))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_DifferentWrapperName, parent.Response.MessageName, parent.Response.Body.WrapperName, defaultName.EncodedName)));
- }
- }
- internal static void ValidateNoHeaders(MethodSignatureGenerator parent)
- {
- if (parent.Request.Headers.Count > 0)
- {
- if (parent.IsEncoded)
- {
- parent.Context.Contract.ServiceContractGenerator.Errors.Add(new MetadataConversionError(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreIgnoredInEncoded, parent.Request.MessageName), true/*isWarning*/));
- }
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreUnsupported, parent.Request.MessageName)));
- }
- if (!parent.Oneway && parent.Response.Headers.Count > 0)
- {
- if (parent.IsEncoded)
- parent.Context.Contract.ServiceContractGenerator.Errors.Add(new MetadataConversionError(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreIgnoredInEncoded, parent.Response.MessageName), true/*isWarning*/));
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ParameterModeException(SR.GetString(SR.SFxCannotImportAsParameters_HeadersAreUnsupported, parent.Response.MessageName)));
- }
- }
- static bool StringEqualOrNull(string overrideValue, string defaultValue)
- {
- return overrideValue == null || String.Equals(overrideValue, defaultValue, StringComparison.Ordinal);
- }
- }
- internal void GenerateTaskSignature(ref OperationFormatStyle style)
- {
- this.Method = this.Context.TaskMethod;
- this.EndMethod = this.Context.TaskMethod;
- this.DefaultName = this.Context.SyncMethod.Name;
- GenerateOperationSignatures(ref style);
- CodeTypeReference resultType = this.Method.ReturnType;
- CodeTypeReference taskReturnType;
- if (resultType.BaseType == ServiceReflector.VoidType.FullName)
- {
- taskReturnType = new CodeTypeReference(ServiceReflector.taskType);
- }
- else
- {
- taskReturnType = new CodeTypeReference(this.Context.ServiceContractGenerator.GetCodeTypeReference(ServiceReflector.taskTResultType).BaseType, resultType);
- }
-
- this.Method.ReturnType = taskReturnType;
- }
- }
- static class CustomAttributeHelper
- {
- internal static void CreateOrOverridePropertyDeclaration<V>(CodeAttributeDeclaration attribute, string propertyName, V value)
- {
- SecurityAttributeGenerationHelper.CreateOrOverridePropertyDeclaration<V>(attribute, propertyName, value);
- }
- internal static CodeAttributeDeclaration FindOrCreateAttributeDeclaration<T>(CodeAttributeDeclarationCollection attributes)
- where T : Attribute
- {
- return SecurityAttributeGenerationHelper.FindOrCreateAttributeDeclaration<T>(attributes);
- }
- internal static CodeAttributeDeclaration GenerateAttributeDeclaration(ServiceContractGenerator generator, Attribute attribute)
- {
- Type attributeType = attribute.GetType();
- Attribute defaultAttribute = (Attribute)Activator.CreateInstance(attributeType);
- MemberInfo[] publicMembers = attributeType.GetMembers(BindingFlags.Instance | BindingFlags.Public);
- Array.Sort<MemberInfo>(publicMembers,
- delegate(MemberInfo a, MemberInfo b)
- {
- return String.Compare(a.Name, b.Name, StringComparison.Ordinal);
- }
- );
- // we should create this reference through ServiceContractGenerator, which tracks referenced assemblies
- CodeAttributeDeclaration attr = new CodeAttributeDeclaration(generator.GetCodeTypeReference(attributeType));
- foreach (MemberInfo member in publicMembers)
- {
- if (member.DeclaringType == typeof(Attribute))
- continue;
- FieldInfo field = member as FieldInfo;
- if (field != null)
- {
- object fieldValue = field.GetValue(attribute);
- object defaultValue = field.GetValue(defaultAttribute);
- if (!object.Equals(fieldValue, defaultValue))
- attr.Arguments.Add(new CodeAttributeArgument(field.Name, GetArgValue(fieldValue)));
- continue;
- }
- PropertyInfo property = member as PropertyInfo;
- if (property != null)
- {
- object propertyValue = property.GetValue(attribute, null);
- object defaultValue = property.GetValue(defaultAttribute, null);
- if (!object.Equals(propertyValue, defaultValue))
- attr.Arguments.Add(new CodeAttributeArgument(property.Name, GetArgValue(propertyValue)));
- continue;
- }
- }
- return attr;
- }
- static CodeExpression GetArgValue(object val)
- {
- Type type = val.GetType();
- if (type.IsPrimitive || type == typeof(string))
- return new CodePrimitiveExpression(val);
- if (type.IsEnum)
- return new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(type), Enum.Format(type, val, "G"));
- Fx.Assert(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Attribute generation is not supported for argument type {0}", type));
- return null;
- }
- }
- }
- class ParameterModeException : Exception
- {
- MessageContractType messageContractType = MessageContractType.WrappedMessageContract;
- public ParameterModeException() { }
- public ParameterModeException(string message) : base(message) { }
- public ParameterModeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
- public MessageContractType MessageContractType
- {
- get { return messageContractType; }
- set { messageContractType = value; }
- }
- }
- }
|