//
// System.Web.Services.Description.SoapProtocolImporter.cs
//
// Author:
// Tim Coleman (tim@timcoleman.com)
// Lluis Sanchez Gual (lluis@ximian.com)
//
// Copyright (C) Tim Coleman, 2002
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.CodeDom;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Configuration;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Configuration;
using System.Collections;
namespace System.Web.Services.Description{
public class SoapProtocolImporter : ProtocolImporter {
#region Fields
SoapBinding soapBinding;
SoapCodeExporter soapExporter;
SoapSchemaImporter soapImporter;
XmlCodeExporter xmlExporter;
XmlSchemaImporter xmlImporter;
CodeIdentifiers memberIds;
ArrayList extensionImporters;
Hashtable headerVariables;
XmlSchemas xmlSchemas;
XmlSchemas soapSchemas;
#endregion // Fields
#region Constructors
public SoapProtocolImporter ()
{
extensionImporters = ExtensionManager.BuildExtensionImporters ();
}
void SetBinding (SoapBinding soapBinding)
{
this.soapBinding = soapBinding;
}
#endregion // Constructors
#region Properties
public override string ProtocolName {
get { return "Soap"; }
}
public SoapBinding SoapBinding {
get { return soapBinding; }
}
public SoapCodeExporter SoapExporter {
get { return soapExporter; }
}
public SoapSchemaImporter SoapImporter {
get { return soapImporter; }
}
public XmlCodeExporter XmlExporter {
get { return xmlExporter; }
}
public XmlSchemaImporter XmlImporter {
get { return xmlImporter; }
}
#endregion // Properties
#region Methods
protected override CodeTypeDeclaration BeginClass ()
{
soapBinding = (SoapBinding) Binding.Extensions.Find (typeof(SoapBinding));
CodeTypeDeclaration codeClass = new CodeTypeDeclaration (ClassName);
#if NET_2_0
codeClass.IsPartial = true;
#endif
string location = null;
if (Port != null) {
SoapAddressBinding sab = (SoapAddressBinding) Port.Extensions.Find (typeof(SoapAddressBinding));
if (sab != null) location = sab.Location;
}
string namspace = (Port != null ? Port.Binding.Namespace : Binding.ServiceDescription.TargetNamespace);
string name = (Port != null ? Port.Name : Binding.Name);
if (Style == ServiceDescriptionImportStyle.Client) {
CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol");
codeClass.BaseTypes.Add (ctr);
}
else {
CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.WebService");
codeClass.BaseTypes.Add (ctr);
CodeAttributeDeclaration attws = new CodeAttributeDeclaration ("System.Web.Services.WebServiceAttribute");
attws.Arguments.Add (GetArg ("Namespace", namspace));
AddCustomAttribute (codeClass, attws, true);
}
CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebServiceBinding");
att.Arguments.Add (GetArg ("Name", name));
att.Arguments.Add (GetArg ("Namespace", namspace));
AddCustomAttribute (codeClass, att, true);
if (Style == ServiceDescriptionImportStyle.Client) {
CodeConstructor cc = new CodeConstructor ();
cc.Attributes = MemberAttributes.Public;
GenerateServiceUrl (location, cc.Statements);
#if NET_2_0
if (ProtocolName.ToUpper () == "SOAP12") {
CodeExpression thisSoapVer = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "SoapVersion");
CodeFieldReferenceExpression soap12Enum =
new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof (SoapProtocolVersion)), "Soap12");
cc.Statements.Add (new CodeAssignStatement (thisSoapVer, soap12Enum));
}
#endif
codeClass.Members.Add (cc);
}
memberIds = new CodeIdentifiers ();
headerVariables = new Hashtable ();
return codeClass;
}
protected override void BeginNamespace ()
{
#if NET_2_0
xmlImporter = new XmlSchemaImporter (LiteralSchemas, base.CodeGenerationOptions, base.CodeGenerator, base.ImportContext);
soapImporter = new SoapSchemaImporter (EncodedSchemas, base.CodeGenerationOptions, base.CodeGenerator, base.ImportContext);
xmlExporter = new XmlCodeExporter (CodeNamespace, null, base.CodeGenerator, base.CodeGenerationOptions, null);
soapExporter = new SoapCodeExporter (CodeNamespace, null, base.CodeGenerator, base.CodeGenerationOptions, null);
#else
xmlImporter = new XmlSchemaImporter (LiteralSchemas, ClassNames);
soapImporter = new SoapSchemaImporter (EncodedSchemas, ClassNames);
xmlExporter = new XmlCodeExporter (CodeNamespace, null);
soapExporter = new SoapCodeExporter (CodeNamespace, null);
#endif
}
protected override void EndClass ()
{
SoapTransportImporter transportImporter = SoapTransportImporter.FindTransportImporter (soapBinding.Transport);
if (transportImporter == null) throw new InvalidOperationException ("Transport '" + soapBinding.Transport + "' not supported");
transportImporter.ImportContext = this;
transportImporter.ImportClass ();
if (xmlExporter.IncludeMetadata.Count > 0 || soapExporter.IncludeMetadata.Count > 0)
{
if (CodeTypeDeclaration.CustomAttributes == null)
CodeTypeDeclaration.CustomAttributes = new CodeAttributeDeclarationCollection ();
CodeTypeDeclaration.CustomAttributes.AddRange (xmlExporter.IncludeMetadata);
CodeTypeDeclaration.CustomAttributes.AddRange (soapExporter.IncludeMetadata);
}
}
protected override void EndNamespace ()
{
}
protected override bool IsBindingSupported ()
{
#if NET_2_0
object o = Binding.Extensions.Find (typeof(SoapBinding));
return o != null && !(o is Soap12Binding);
#else
return Binding.Extensions.Find (typeof(SoapBinding)) != null;
#endif
}
[MonoTODO]
protected override bool IsOperationFlowSupported (OperationFlow flow)
{
throw new NotImplementedException ();
}
static readonly char [] whitespaces = new char [] {' ', '\t', '\n', '\r'};
protected virtual bool IsSoapEncodingPresent (string uriList)
{
foreach (string s in uriList.Split (whitespaces))
if (s == "http://schemas.xmlsoap.org/soap/encoding/")
return true;
return false;
}
protected override CodeMemberMethod GenerateMethod ()
{
try
{
SoapOperationBinding soapOper = OperationBinding.Extensions.Find (typeof (SoapOperationBinding)) as SoapOperationBinding;
if (soapOper == null) throw new InvalidOperationException ("Soap operation binding not found");
SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
SoapBodyBinding isbb = null;
XmlMembersMapping inputMembers = null;
bool isWrapped = CheckIsWrapped ();
isbb = OperationBinding.Input.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
if (isbb == null) throw new InvalidOperationException ("Soap body binding not found");
inputMembers = ImportMembersMapping (InputMessage, isbb, style, false, isWrapped);
if (inputMembers == null) throw new InvalidOperationException ("Input message not declared");
// If OperationBinding.Output is null, it is an OneWay operation
SoapBodyBinding osbb = null;
XmlMembersMapping outputMembers = null;
if (OperationBinding.Output != null) {
osbb = OperationBinding.Output.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
if (osbb == null) throw new InvalidOperationException ("Soap body binding not found");
outputMembers = ImportMembersMapping (OutputMessage, osbb, style, true, isWrapped);
if (outputMembers == null) throw new InvalidOperationException ("Output message not declared");
}
CodeMemberMethod met = GenerateMethod (memberIds, soapOper, isbb, inputMembers, outputMembers);
if (isbb.Use == SoapBindingUse.Literal)
xmlExporter.ExportMembersMapping (inputMembers);
else
soapExporter.ExportMembersMapping (inputMembers);
if (osbb != null) {
if (osbb.Use == SoapBindingUse.Literal)
xmlExporter.ExportMembersMapping (outputMembers);
else
soapExporter.ExportMembersMapping (outputMembers);
}
foreach (SoapExtensionImporter eximporter in extensionImporters)
{
eximporter.ImportContext = this;
eximporter.ImportMethod (met.CustomAttributes);
}
return met;
}
catch (InvalidOperationException ex)
{
UnsupportedOperationBindingWarning (ex.Message);
return null;
}
}
bool CheckIsWrapped ()
{
return (OutputMessage == null || (OutputMessage.Parts.Count == 1 && OutputMessage.Parts[0].Name == "parameters")) &&
(InputMessage == null || (InputMessage.Parts.Count == 1 && InputMessage.Parts[0].Name == "parameters"));
}
XmlMembersMapping ImportMembersMapping (Message msg, SoapBodyBinding sbb, SoapBindingStyle style, bool output, bool wrapped)
{
string elemName = Operation.Name;
if (output) elemName += "Response";
if (wrapped)
{
// Wrapped parameter style
MessagePart part = msg.Parts[0];
if (sbb.Use == SoapBindingUse.Encoded)
{
SoapSchemaMember ssm = new SoapSchemaMember ();
ssm.MemberName = part.Name;
ssm.MemberType = part.Type;
return soapImporter.ImportMembersMapping (elemName, part.Type.Namespace, ssm);
}
else
return xmlImporter.ImportMembersMapping (part.Element);
}
else
{
if (sbb.Use == SoapBindingUse.Encoded)
{
SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count];
for (int n=0; n<mems.Length; n++)
{
SoapSchemaMember mem = new SoapSchemaMember();
mem.MemberName = msg.Parts[n].Name;
mem.MemberType = msg.Parts[n].Type;
mems[n] = mem;
}
// Rpc messages always have a wrapping element
if (style == SoapBindingStyle.Rpc)
return soapImporter.ImportMembersMapping (elemName, sbb.Namespace, mems, true);
else
return soapImporter.ImportMembersMapping ("", "", mems, false);
}
else
{
if (style == SoapBindingStyle.Rpc)
throw new InvalidOperationException ("The combination of style=rpc with use=literal is not supported");
if (msg.Parts.Count == 1 && msg.Parts[0].Type != XmlQualifiedName.Empty)
return xmlImporter.ImportAnyType (msg.Parts[0].Type, null);
else
{
XmlQualifiedName[] pnames = new XmlQualifiedName [msg.Parts.Count];
for (int n=0; n<pnames.Length; n++)
pnames[n] = msg.Parts[n].Element;
return xmlImporter.ImportMembersMapping (pnames);
}
}
}
}
CodeMemberMethod GenerateMethod (CodeIdentifiers memberIds, SoapOperationBinding soapOper, SoapBodyBinding bodyBinding, XmlMembersMapping inputMembers, XmlMembersMapping outputMembers)
{
CodeIdentifiers pids = new CodeIdentifiers ();
CodeMemberMethod method = new CodeMemberMethod ();
CodeMemberMethod methodBegin = new CodeMemberMethod ();
CodeMemberMethod methodEnd = new CodeMemberMethod ();
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
methodBegin.Attributes = MemberAttributes.Public | MemberAttributes.Final;
methodEnd.Attributes = MemberAttributes.Public | MemberAttributes.Final;
SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
// Find unique names for temporary variables
for (int n=0; n<inputMembers.Count; n++)
pids.AddUnique (inputMembers[n].MemberName, inputMembers[n]);
if (outputMembers != null)
for (int n=0; n<outputMembers.Count; n++)
pids.AddUnique (outputMembers[n].MemberName, outputMembers[n]);
string varAsyncResult = pids.AddUnique ("asyncResult","asyncResult");
string varResults = pids.AddUnique ("results","results");
string varCallback = pids.AddUnique ("callback","callback");
string varAsyncState = pids.AddUnique ("asyncState","asyncState");
string messageName = memberIds.AddUnique(CodeIdentifier.MakeValid(Operation.Name),method);
method.Name = CodeIdentifier.MakeValid(Operation.Name);
if (method.Name == ClassName) method.Name += "1";
methodBegin.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("Begin" + method.Name),method);
methodEnd.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("End" + method.Name),method);
method.ReturnType = new CodeTypeReference (typeof(void));
methodEnd.ReturnType = new CodeTypeReference (typeof(void));
methodEnd.Parameters.Add (new CodeParameterDeclarationExpression (typeof (IAsyncResult),varAsyncResult));
CodeExpression[] paramArray = new CodeExpression [inputMembers.Count];
CodeParameterDeclarationExpression[] outParams = new CodeParameterDeclarationExpression [outputMembers != null ? outputMembers.Count : 0];
for (int n=0; n<inputMembers.Count; n++)
{
CodeParameterDeclarationExpression param = GenerateParameter (inputMembers[n], FieldDirection.In);
method.Parameters.Add (param);
GenerateMemberAttributes (inputMembers, inputMembers[n], bodyBinding.Use, param);
methodBegin.Parameters.Add (GenerateParameter (inputMembers[n], FieldDirection.In));
paramArray [n] = new CodeVariableReferenceExpression (param.Name);
}
if (outputMembers != null)
{
bool hasReturn = false;
for (int n=0; n<outputMembers.Count; n++)
{
CodeParameterDeclarationExpression cpd = GenerateParameter (outputMembers[n], FieldDirection.Out);
outParams [n] = cpd;
bool found = false;
foreach (CodeParameterDeclarationExpression ip in method.Parameters)
{
if (ip.Name == cpd.Name && ip.Type.BaseType == cpd.Type.BaseType) {
ip.Direction = FieldDirection.Ref;
methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
found = true;
break;
}
}
if (found) continue;
if (!hasReturn)
{
hasReturn = true;
method.ReturnType = cpd.Type;
methodEnd.ReturnType = cpd.Type;
GenerateReturnAttributes (outputMembers, outputMembers[n], bodyBinding.Use, method);
outParams [n] = null;
continue;
}
method.Parameters.Add (cpd);
GenerateMemberAttributes (outputMembers, outputMembers[n], bodyBinding.Use, cpd);
methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
}
}
methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (AsyncCallback),varCallback));
methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object),varAsyncState));
methodBegin.ReturnType = new CodeTypeReference (typeof(IAsyncResult));
// Array of input parameters
CodeArrayCreateExpression methodParams;
if (paramArray.Length > 0)
methodParams = new CodeArrayCreateExpression (typeof(object), paramArray);
else
methodParams = new CodeArrayCreateExpression (typeof(object), 0);
// Assignment of output parameters
CodeStatementCollection outAssign = new CodeStatementCollection ();
CodeVariableReferenceExpression arrVar = new CodeVariableReferenceExpression (varResults);
for (int n=0; n<outParams.Length; n++)
{
CodeExpression index = new CodePrimitiveExpression (n);
if (outParams[n] == null)
{
CodeExpression res = new CodeCastExpression (method.ReturnType, new CodeArrayIndexerExpression (arrVar, index));
outAssign.Add (new CodeMethodReturnStatement (res));
}
else
{
CodeExpression res = new CodeCastExpression (outParams[n].Type, new CodeArrayIndexerExpression (arrVar, index));
CodeExpression var = new CodeVariableReferenceExpression (outParams[n].Name);
outAssign.Insert (0, new CodeAssignStatement (var, res));
}
}
if (Style == ServiceDescriptionImportStyle.Client)
{
// Invoke call
CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
CodeMethodInvokeExpression inv;
CodeVariableDeclarationStatement dec;
inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, methodParams);
if (outputMembers != null && outputMembers.Count > 0)
{
dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
method.Statements.Add (dec);
method.Statements.AddRange (outAssign);
}
else
method.Statements.Add (inv);
// Begin Invoke Call
CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, methodParams, expCallb, expAsyncs);
methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
// End Invoke call
CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
if (outputMembers != null && outputMembers.Count > 0)
{
dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
methodEnd.Statements.Add (dec);
methodEnd.Statements.AddRange (outAssign);
}
else
methodEnd.Statements.Add (inv);
}
else {
method.Attributes = MemberAttributes.Public | MemberAttributes.Abstract;
}
// Attributes
ImportHeaders (method);
CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebMethodAttribute");
if (messageName != method.Name) att.Arguments.Add (GetArg ("MessageName",messageName));
AddCustomAttribute (method, att, (Style == ServiceDescriptionImportStyle.Server));
if (style == SoapBindingStyle.Rpc)
{
att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapRpcMethodAttribute");
att.Arguments.Add (GetArg (soapOper.SoapAction));
if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
}
else
{
if (outputMembers != null && (inputMembers.ElementName == "" && outputMembers.ElementName != "" ||
inputMembers.ElementName != "" && outputMembers.ElementName == ""))
throw new InvalidOperationException ("Parameter style is not the same for the input message and output message");
att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapDocumentMethodAttribute");
att.Arguments.Add (GetArg (soapOper.SoapAction));
if (inputMembers.ElementName != "") {
if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Wrapped"));
}
else
att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Bare"));
if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
att.Arguments.Add (GetEnumArg ("Use", "System.Web.Services.Description.SoapBindingUse", bodyBinding.Use.ToString()));
}
AddCustomAttribute (method, att, true);
CodeTypeDeclaration.Members.Add (method);
if (Style == ServiceDescriptionImportStyle.Client) {
CodeTypeDeclaration.Members.Add (methodBegin);
CodeTypeDeclaration.Members.Add (methodEnd);
}
return method;
}
CodeParameterDeclarationExpression GenerateParameter (XmlMemberMapping member, FieldDirection dir)
{
#if NET_2_0
string type = member.GenerateTypeName (CodeGenerator);
#else
string type = member.TypeFullName;
#endif
CodeParameterDeclarationExpression par = new CodeParameterDeclarationExpression (type, member.MemberName);
par.Direction = dir;
return par;
}
void GenerateMemberAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeParameterDeclarationExpression param)
{
if (use == SoapBindingUse.Literal)
xmlExporter.AddMappingMetadata (param.CustomAttributes, member, members.Namespace);
else
soapExporter.AddMappingMetadata (param.CustomAttributes, member);
}
void GenerateReturnAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeMemberMethod method)
{
if (use == SoapBindingUse.Literal)
xmlExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, members.Namespace, (member.ElementName != method.Name + "Result"));
else
soapExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, (member.ElementName != method.Name + "Result"));
}
void ImportHeaders (CodeMemberMethod method)
{
foreach (object ob in OperationBinding.Input.Extensions)
{
SoapHeaderBinding hb = ob as SoapHeaderBinding;
if (hb == null) continue;
if (HasHeader (OperationBinding.Output, hb))
ImportHeader (method, hb, SoapHeaderDirection.In | SoapHeaderDirection.Out);
else
ImportHeader (method, hb, SoapHeaderDirection.In);
}
if (OperationBinding.Output == null) return;
foreach (object ob in OperationBinding.Output.Extensions)
{
SoapHeaderBinding hb = ob as SoapHeaderBinding;
if (hb == null) continue;
if (!HasHeader (OperationBinding.Input, hb))
ImportHeader (method, hb, SoapHeaderDirection.Out);
}
}
bool HasHeader (MessageBinding msg, SoapHeaderBinding hb)
{
if (msg == null) return false;
foreach (object ob in msg.Extensions)
{
SoapHeaderBinding mhb = ob as SoapHeaderBinding;
if ((mhb != null) && (mhb.Message == hb.Message) && (mhb.Part == hb.Part))
return true;
}
return false;
}
void ImportHeader (CodeMemberMethod method, SoapHeaderBinding hb, SoapHeaderDirection direction)
{
Message msg = ServiceDescriptions.GetMessage (hb.Message);
if (msg == null) throw new InvalidOperationException ("Message " + hb.Message + " not found");
MessagePart part = msg.Parts [hb.Part];
if (part == null) throw new InvalidOperationException ("Message part " + hb.Part + " not found in message " + hb.Message);
XmlTypeMapping map;
string hname;
if (hb.Use == SoapBindingUse.Literal)
{
map = xmlImporter.ImportDerivedTypeMapping (part.Element, typeof (SoapHeader));
hname = part.Element.Name;
xmlExporter.ExportTypeMapping (map);
}
else
{
map = soapImporter.ImportDerivedTypeMapping (part.Type, typeof (SoapHeader), true);
hname = part.Type.Name;
soapExporter.ExportTypeMapping (map);
}
string varName = headerVariables [map] as string;
if (varName == null)
{
if (hname == map.TypeName)
varName = memberIds.AddUnique(CodeIdentifier.MakeValid (hname + "Value"),hb);
else
varName = memberIds.AddUnique(CodeIdentifier.MakeValid (hname),hb);
#if NET_2_0
string propName = varName;
varName = varName + "Field";
#endif
headerVariables.Add (map, varName);
CodeMemberField codeField = new CodeMemberField (map.TypeFullName, varName);
CodeTypeDeclaration.Members.Add (codeField);
#if NET_2_0
codeField.Attributes = MemberAttributes.Private;
CodeMemberProperty codeProperty = new CodeMemberProperty ();
codeProperty.Name = propName;
codeProperty.Type = new CodeTypeReference (map.TypeFullName);
codeProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
codeProperty.HasGet = codeProperty.HasSet = true;
CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), varName);
codeProperty.SetStatements.Add (new CodeAssignStatement (ce, new CodePropertySetValueReferenceExpression()));
codeProperty.GetStatements.Add (new CodeMethodReturnStatement (ce));
CodeTypeDeclaration.Members.Add (codeProperty);
varName = propName;
#else
codeField.Attributes = MemberAttributes.Public;
#endif
}
CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapHeaderAttribute");
att.Arguments.Add (GetArg (varName));
#if ONLY_1_0
att.Arguments.Add (GetArg ("Required", false));
#endif
if (direction != SoapHeaderDirection.In) att.Arguments.Add (GetEnumArg ("Direction", "System.Web.Services.Protocols.SoapHeaderDirection", direction.ToString ()));
AddCustomAttribute (method, att, true);
}
#endregion
}
#if NET_2_0
internal class Soap12ProtocolImporter : SoapProtocolImporter
{
public override string ProtocolName {
get { return "Soap12"; }
}
protected override bool IsBindingSupported ()
{
return Binding.Extensions.Find (typeof(Soap12Binding)) != null;
}
}
#endif
}
|