diff --git a/src/Spring/Spring.Services/Web/Services/WebServiceProxyFactory.cs b/src/Spring/Spring.Services/Web/Services/WebServiceProxyFactory.cs
index 84b92ac2..11c6c5c0 100644
--- a/src/Spring/Spring.Services/Web/Services/WebServiceProxyFactory.cs
+++ b/src/Spring/Spring.Services/Web/Services/WebServiceProxyFactory.cs
@@ -1,1184 +1,1171 @@
-#region License
-
-/*
- * Copyright © 2002-2007 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#endregion
-
-#region Imports
-
-using System;
-using System.Collections;
-using System.Globalization;
-using System.Xml;
-using System.Xml.Schema;
-using System.Xml.Serialization;
-using System.Net;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Web.Services;
-using System.Web.Services.Description;
-using System.Web.Services.Protocols;
-using System.Web.Services.Discovery;
-
-using Spring.Core;
-using Spring.Objects.Factory;
-using Spring.Objects.Factory.Config;
-using Spring.Proxy;
-using Spring.Util;
-using Spring.Objects;
-using Spring.Core.IO;
-using Spring.Expressions;
-
-#endregion
-
-namespace Spring.Web.Services
-{
- ///
- /// Factory Object that dynamically implements service interface for web service.
- ///
- ///
- ///
- /// This factory object should be used to obtain reference to a web service
- /// that can be safely cast to a service interface, which allows client code to code
- /// against interface, and not directly against the web service.
- ///
- ///
- /// The WSDL contract needs to conform to WS-I Basic Profiles.
- ///
- ///
- /// Bruno Baia
- /// Aleksandar Seovic
- public class WebServiceProxyFactory : IConfigurableFactoryObject, IInitializingObject
- {
- #region Logging
-
- private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(WebServiceProxyFactory));
-
- #endregion
-
- #region Fields
-
- private IObjectDefinition _productTemplate;
- private Type _webServiceProxyBaseType = typeof(SoapHttpClientProtocol);
- private IResource _serviceUri;
- private Type _proxyType;
- private Type _serviceInterface;
- private NetworkCredential _credential;
- private string _proxyUrl;
- private NetworkCredential _proxyCredential;
- private string _bindingName;
- private IList _typeAttributes = new ArrayList();
- private IDictionary _memberAttributes = new Hashtable();
-
- ///
- /// The web service proxy default constructor.
- ///
- protected ConstructorInfo proxyConstructor;
-
- #endregion
-
- #region Constructor(s) / Destructor
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- public WebServiceProxyFactory()
- {
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets or sets the base type that web service proxy should inherit.
- ///
- ///
- /// Default is
- ///
- [Obsolete("This property is obsolete, it has been replaced by WebServiceProxyBaseType")]
- public Type ClientProtocolType
- {
- get { return _webServiceProxyBaseType; }
- set { _webServiceProxyBaseType = value; }
- }
-
- ///
- /// Gets or sets the base type that web service proxy should inherit.
- ///
- ///
- /// Default is
- ///
- public Type WebServiceProxyBaseType
- {
- get { return _webServiceProxyBaseType; }
- set { _webServiceProxyBaseType = value; }
- }
-
- ///
- /// Gets or sets the URI for an
- /// that contains the web service description (WSDL).
- ///
- public IResource ServiceUri
- {
- get { return _serviceUri; }
- set { _serviceUri = value; }
- }
-
- ///
- /// Gets or sets type of the proxy class to wrap.
- ///
- public Type ProxyType
- {
- get { return _proxyType; }
- set { _proxyType = value; }
- }
-
- ///
- /// Gets or sets service interface that proxy should implement.
- ///
- public Type ServiceInterface
- {
- get { return _serviceInterface; }
- set { _serviceInterface = value; }
- }
-
- ///
- /// Gets or sets the instance
- /// to use when connecting to a server that requires authentication.
- ///
- public NetworkCredential Credential
- {
- get { return _credential; }
- set { _credential = value; }
- }
-
- ///
- /// Gets or sets the url of the proxy server to use for retrieving the WSDL.
- ///
- ///
- ///
- /// This only applies when using an as uri.
- ///
- ///
- /// The default is to use the system proxy setting.
- ///
- ///
- public string ProxyUrl
- {
- get { return _proxyUrl; }
- set { _proxyUrl = value; }
- }
-
- ///
- /// Gets or sets the instance
- /// to use when connecting to a proxy server that requires authentication.
- ///
- ///
- ///
- /// This only applies when using an as uri.
- ///
- ///
- public NetworkCredential ProxyCredential
- {
- get { return _proxyCredential; }
- set { _proxyCredential = value; }
- }
-
- ///
- /// Gets or sets the web service binding name to use for the proxy.
- ///
- public string BindingName
- {
- get { return _bindingName; }
- set { _bindingName = value; }
- }
-
- ///
- /// Gets or sets a list of custom attributes
- /// that should be applied to a proxy class.
- ///
- public IList TypeAttributes
- {
- get { return _typeAttributes; }
- set { _typeAttributes = value; }
- }
-
- ///
- /// Gets or sets a dictionary of custom attributes
- /// that should be applied to web service members.
- ///
- ///
- /// Dictionary key is an expression that members can be matched against.
- /// Value is a list of attributes that should be applied
- /// to each member that matches expression.
- ///
- public IDictionary MemberAttributes
- {
- get { return _memberAttributes; }
- set { _memberAttributes = value; }
- }
-
- #endregion
-
- #region IConfigurableFactoryObject Members
-
- ///
- /// Returns type of the web service proxy.
- ///
- public virtual Type ObjectType
- {
- get { return (proxyConstructor != null ? proxyConstructor.DeclaringType : ServiceInterface); }
- }
-
- ///
- /// Creates new instance of the web service proxy.
- ///
- /// New instance of the web service proxy.
- public virtual object GetObject()
- {
- if (proxyConstructor == null)
- {
- GenerateProxy();
- }
-
- return ObjectUtils.InstantiateType(proxyConstructor, ObjectUtils.EmptyObjects);
- }
-
- ///
- /// Always returns false.
- ///
- public virtual bool IsSingleton
- {
- get { return false; }
- }
-
- ///
- /// Gets or sets the template object definition
- /// that should be used to configure proxy instance.
- ///
- public virtual IObjectDefinition ProductTemplate
- {
- get { return _productTemplate; }
- set { _productTemplate = value; }
- }
-
- #endregion
-
- #region IInitializingObject Members
-
- ///
- /// Initializes factory object.
- ///
- public virtual void AfterPropertiesSet()
- {
- ValidateConfiguration();
- }
-
- #endregion
-
- #region Protected Methods
-
- ///
- /// Validates the configuration.
- ///
- protected virtual void ValidateConfiguration()
- {
- if (ServiceUri == null && ProxyType == null)
- {
- throw new ArgumentException("ServiceUri or ProxyType property is required.");
- }
- if (ServiceInterface == null)
- {
- throw new ArgumentException("The ServiceInterface property is required.");
- }
- if (!ServiceInterface.IsInterface)
- {
- throw new ArgumentException("ServiceInterface must be an interface");
- }
- if (WebServiceProxyBaseType.IsSealed)
- {
- throw new ArgumentException("Web service client proxy cannot be created for a sealed class [" + WebServiceProxyBaseType.FullName + "]");
- }
- }
-
- ///
- /// Generates the web service proxy type.
- ///
- protected virtual void GenerateProxy()
- {
- IProxyTypeBuilder builder;
- if (ProxyType != null)
- {
- // Wrap .NET generated proxy class or another
- builder = new WebServiceProxyProxyTypeBuilder();
- builder.TargetType = ProxyType;
- }
- else
- {
- // Dynamically generates proxy class from WSDL
- builder = new SoapHttpClientProxyTypeBuilder(
- ServiceUri, GetWsDocuments(ServiceUri), BindingName);
- builder.BaseType = WebServiceProxyBaseType;
- }
-
- builder.Interfaces = ReflectionUtils.ToInterfaceArray(ServiceInterface);
- builder.TypeAttributes = TypeAttributes;
- builder.MemberAttributes = MemberAttributes;
-
- Type wrapper = builder.BuildProxyType();
-
- proxyConstructor = wrapper.GetConstructor(Type.EmptyTypes);
-
- #region Instrumentation
-
- if (LOG.IsDebugEnabled)
- {
- if (ServiceUri != null)
- {
- LOG.Debug(
- String.Format("Generated client proxy type [{0}] for web service [{1}]", wrapper.FullName,
- ServiceUri.Description));
- }
- else if (ProxyType != null)
- {
- LOG.Debug(
- String.Format("Generated client proxy type [{0}] for web service based on provided proxy type [{1}]", wrapper.FullName,
- ProxyType.FullName));
- }
- }
-
- #endregion
- }
-
- #endregion
-
- #region Private Methods
-
- ///
- /// Gets XML Web Services documents from a Spring resource.
- ///
- private DiscoveryClientDocumentCollection GetWsDocuments(IResource resource)
- {
- try
- {
- if (ServiceUri is UrlResource ||
- ServiceUri is FileSystemResource)
- {
- DiscoveryClientProtocol dcProtocol = new DiscoveryClientProtocol();
- dcProtocol.AllowAutoRedirect = true;
- dcProtocol.Credentials = CreateCredentials();
- dcProtocol.Proxy = ConfigureProxy();
- dcProtocol.DiscoverAny(resource.Uri.AbsoluteUri);
- dcProtocol.ResolveAll();
-
- return dcProtocol.Documents;
- }
- else
- {
- DiscoveryClientDocumentCollection dcdc = new DiscoveryClientDocumentCollection();
- dcdc[resource.Description] = ServiceDescription.Read(resource.InputStream);
- return dcdc;
- }
- }
- catch (Exception ex)
- {
- throw new ArgumentException(String.Format("Couldn't retrieve the description of the web service located at '{0}'.", resource.Description), ex);
- }
- }
-
- private IWebProxy ConfigureProxy()
- {
- IWebProxy webProxy = null;
- if (ProxyUrl != null)
- {
- webProxy = new WebProxy(ProxyUrl);
- }
- if (ProxyCredential != null)
- {
- if (webProxy == null)
- {
-#if !NET_2_0
- webProxy = GlobalProxySelection.Select;
-#else
- webProxy = WebRequest.DefaultWebProxy;
-#endif
- }
- webProxy.Credentials = ProxyCredential;
- }
-
- return webProxy;
- }
-
- private ICredentials CreateCredentials()
- {
- if (Credential != null)
- {
- CredentialCache credentialCache = new CredentialCache();
-
- Uri wsUri = new Uri(ServiceUri.Uri.AbsoluteUri.Substring(0, ServiceUri.Uri.AbsoluteUri.Length - ServiceUri.Uri.AbsolutePath.Length));
- IEnumerator enumerator = AuthenticationManager.RegisteredModules;
- while (enumerator.MoveNext())
- {
- credentialCache.Add(wsUri, ((IAuthenticationModule)enumerator.Current).AuthenticationType, Credential);
- }
-
- return credentialCache;
- }
- else
- {
- return CredentialCache.DefaultCredentials;
- }
- }
-
- #endregion
-
- #region SoapHttpClientProxyTypeBuilder inner class implementation
-
- ///
- /// Proxy type builder that can be used to create a proxy for
- /// derived classes.
- ///
- private sealed class SoapHttpClientProxyTypeBuilder : AbstractProxyTypeBuilder
- {
- #region Logging
-
- private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(SoapHttpClientProxyTypeBuilder));
-
- #endregion
-
- #region Fields
-
- // Binding/Type related
- private IResource serviceUri;
- private ServiceDescriptionCollection wsDescriptions;
- private XmlSchemaImporter schemaImporter;
- private Binding wsBinding;
- private string wsUrl;
-
- // Operation/Method related
- private Operation operation;
- private OperationBinding operationBinding;
- private SoapOperationBinding soapOperationBinding;
- private XmlMembersMapping inputMembersMapping;
- private XmlMembersMapping outputMembersMapping;
-
- #endregion
-
- #region Constructor(s) / Destructor
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- /// The URI that contains the Web Service meta info (WSDL).
- /// The XML Web Service documents to use to create the proxy.
- /// The name of the Web Service binding to use.
- public SoapHttpClientProxyTypeBuilder(IResource serviceUri,
- DiscoveryClientDocumentCollection wsDocuments, string bindingName)
- {
- this.serviceUri = serviceUri;
-
- Name = "SoapHttpClientProxy";
- ProxyTargetAttributes = false;
-
- Initialize(wsDocuments, bindingName);
- }
-
- #endregion
-
- #region IProxyTypeBuilder Members
-
- ///
- /// Creates the proxy type.
- ///
- /// The generated proxy class.
- public override Type BuildProxyType()
- {
- if (Interfaces == null || Interfaces.Length == 0)
- {
- throw new ArgumentException(
- "Web service client proxy must implement at least one interface.");
- }
-
- TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
-
- // apply custom attributes to the proxy type.
- ApplyTypeAttributes(typeBuilder, TargetType);
-
- // create constructors
- ImplementConstructors(typeBuilder);
-
- // implement service interfaces
- foreach (Type intf in Interfaces)
- {
- ImplementInterface(typeBuilder,
- new SoapHttpClientProxyMethodBuilder(typeBuilder, this),
- intf, TargetType);
- }
-
- return typeBuilder.CreateType();
- }
-
- #endregion
-
- #region IProxyTypeGenerator Members
-
- ///
- /// Generates the IL instructions that pushes
- /// the target instance on which calls should be delegated to.
- ///
- /// The IL generator to use.
- public override void PushTarget(ILGenerator il)
- {
- PushProxy(il);
- }
-
- #endregion
-
- #region Protected Methods
-
- ///
- /// Implements constructors for the proxy class.
- ///
- ///
- /// The to use.
- ///
- protected override void ImplementConstructors(TypeBuilder builder)
- {
- MethodAttributes attributes = MethodAttributes.Public |
- MethodAttributes.HideBySig | MethodAttributes.SpecialName |
- MethodAttributes.RTSpecialName;
- ConstructorBuilder cb = builder.DefineConstructor(attributes,
- CallingConventions.Standard, Type.EmptyTypes);
-
- ILGenerator il = cb.GetILGenerator();
-
- PushProxy(il);
- il.Emit(OpCodes.Call, this.BaseType.GetConstructor(Type.EmptyTypes));
-
- // Set Url Property
- PushProxy(il);
- il.Emit(OpCodes.Ldstr, this.wsUrl);
- il.Emit(OpCodes.Call, this.BaseType.GetMethod("set_Url", BindingFlags.Public | BindingFlags.Instance));
-
- il.Emit(OpCodes.Ret);
- }
-
- protected override void ApplyMethodAttributes(
- MethodBuilder methodBuilder, MethodInfo targetMethod)
- {
- MoveToMethod(targetMethod);
-
- base.ApplyMethodAttributes(methodBuilder, targetMethod);
- }
-
- protected override IList GetTypeAttributes(Type type)
- {
- IList attrs = base.GetTypeAttributes(type);
-
- // Add the WebServiceBindingAttribute
- attrs.Add(CreateWebServiceBindingAttribute(this.wsBinding));
-
- return attrs;
- }
-
- protected override IList GetMethodAttributes(MethodInfo method)
- {
- IList attrs = base.GetMethodAttributes(method);
-
- // Add the SoapMethodAttribute
- attrs.Add(CreateSoapMethodAttribute(
- operation, operationBinding, soapOperationBinding, inputMembersMapping, outputMembersMapping));
-
- return attrs;
- }
-
-#if NET_2_0
- protected override IList GetMethodReturnTypeAttributes(MethodInfo method)
- {
- IList attrs = base.GetMethodReturnTypeAttributes(method);
-
- // Add the XmlElementAttribute if needed
- if (operation.Messages.Output != null)
- {
- if (method.ReturnType != typeof(void))
- {
- if (outputMembersMapping.Count > 0)
- {
- XmlMemberMapping outMemberMapping = outputMembersMapping[0];
- bool useMemberName = (outMemberMapping.MemberName != operation.Name + "Result");
- bool useNamespace = outMemberMapping.Namespace != outputMembersMapping.Namespace;
- if (useMemberName || useNamespace)
- {
+#region License
+
+/*
+ * Copyright © 2002-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Serialization;
+using System.Net;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Web.Services;
+using System.Web.Services.Description;
+using System.Web.Services.Protocols;
+using System.Web.Services.Discovery;
+
+using Spring.Core;
+using Spring.Objects.Factory;
+using Spring.Objects.Factory.Config;
+using Spring.Proxy;
+using Spring.Util;
+using Spring.Objects;
+using Spring.Core.IO;
+using Spring.Expressions;
+
+#endregion
+
+namespace Spring.Web.Services
+{
+ ///
+ /// Factory Object that dynamically implements service interface for web service.
+ ///
+ ///
+ ///
+ /// This factory object should be used to obtain reference to a web service
+ /// that can be safely cast to a service interface, which allows client code to code
+ /// against interface, and not directly against the web service.
+ ///
+ ///
+ /// The WSDL contract needs to conform to WS-I Basic Profiles.
+ ///
+ ///
+ /// Bruno Baia
+ /// Aleksandar Seovic
+ public class WebServiceProxyFactory : IConfigurableFactoryObject, IInitializingObject
+ {
+ #region Logging
+
+ private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(WebServiceProxyFactory));
+
+ #endregion
+
+ #region Fields
+
+ private IObjectDefinition _productTemplate;
+ private Type _webServiceProxyBaseType = typeof(SoapHttpClientProtocol);
+ private IResource _serviceUri;
+ private Type _proxyType;
+ private Type _serviceInterface;
+ private NetworkCredential _credential;
+ private string _proxyUrl;
+ private NetworkCredential _proxyCredential;
+ private string _bindingName;
+ private IList _typeAttributes = new ArrayList();
+ private IDictionary _memberAttributes = new Hashtable();
+
+ ///
+ /// The web service proxy default constructor.
+ ///
+ protected ConstructorInfo proxyConstructor;
+
+ #endregion
+
+ #region Constructor(s) / Destructor
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ public WebServiceProxyFactory()
+ {
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets or sets the base type that web service proxy should inherit.
+ ///
+ ///
+ /// Default is
+ ///
+ public Type WebServiceProxyBaseType
+ {
+ get { return _webServiceProxyBaseType; }
+ set { _webServiceProxyBaseType = value; }
+ }
+
+ ///
+ /// Gets or sets the URI for an
+ /// that contains the web service description (WSDL).
+ ///
+ public IResource ServiceUri
+ {
+ get { return _serviceUri; }
+ set { _serviceUri = value; }
+ }
+
+ ///
+ /// Gets or sets type of the proxy class to wrap.
+ ///
+ public Type ProxyType
+ {
+ get { return _proxyType; }
+ set { _proxyType = value; }
+ }
+
+ ///
+ /// Gets or sets service interface that proxy should implement.
+ ///
+ public Type ServiceInterface
+ {
+ get { return _serviceInterface; }
+ set { _serviceInterface = value; }
+ }
+
+ ///
+ /// Gets or sets the instance
+ /// to use when connecting to a server that requires authentication.
+ ///
+ public NetworkCredential Credential
+ {
+ get { return _credential; }
+ set { _credential = value; }
+ }
+
+ ///
+ /// Gets or sets the url of the proxy server to use for retrieving the WSDL.
+ ///
+ ///
+ ///
+ /// This only applies when using an as uri.
+ ///
+ ///
+ /// The default is to use the system proxy setting.
+ ///
+ ///
+ public string ProxyUrl
+ {
+ get { return _proxyUrl; }
+ set { _proxyUrl = value; }
+ }
+
+ ///
+ /// Gets or sets the instance
+ /// to use when connecting to a proxy server that requires authentication.
+ ///
+ ///
+ ///
+ /// This only applies when using an as uri.
+ ///
+ ///
+ public NetworkCredential ProxyCredential
+ {
+ get { return _proxyCredential; }
+ set { _proxyCredential = value; }
+ }
+
+ ///
+ /// Gets or sets the web service binding name to use for the proxy.
+ ///
+ public string BindingName
+ {
+ get { return _bindingName; }
+ set { _bindingName = value; }
+ }
+
+ ///
+ /// Gets or sets a list of custom attributes
+ /// that should be applied to a proxy class.
+ ///
+ public IList TypeAttributes
+ {
+ get { return _typeAttributes; }
+ set { _typeAttributes = value; }
+ }
+
+ ///
+ /// Gets or sets a dictionary of custom attributes
+ /// that should be applied to web service members.
+ ///
+ ///
+ /// Dictionary key is an expression that members can be matched against.
+ /// Value is a list of attributes that should be applied
+ /// to each member that matches expression.
+ ///
+ public IDictionary MemberAttributes
+ {
+ get { return _memberAttributes; }
+ set { _memberAttributes = value; }
+ }
+
+ #endregion
+
+ #region IConfigurableFactoryObject Members
+
+ ///
+ /// Returns type of the web service proxy.
+ ///
+ public virtual Type ObjectType
+ {
+ get { return (proxyConstructor != null ? proxyConstructor.DeclaringType : ServiceInterface); }
+ }
+
+ ///
+ /// Creates new instance of the web service proxy.
+ ///
+ /// New instance of the web service proxy.
+ public virtual object GetObject()
+ {
+ if (proxyConstructor == null)
+ {
+ GenerateProxy();
+ }
+
+ return ObjectUtils.InstantiateType(proxyConstructor, ObjectUtils.EmptyObjects);
+ }
+
+ ///
+ /// Always returns false.
+ ///
+ public virtual bool IsSingleton
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Gets or sets the template object definition
+ /// that should be used to configure proxy instance.
+ ///
+ public virtual IObjectDefinition ProductTemplate
+ {
+ get { return _productTemplate; }
+ set { _productTemplate = value; }
+ }
+
+ #endregion
+
+ #region IInitializingObject Members
+
+ ///
+ /// Initializes factory object.
+ ///
+ public virtual void AfterPropertiesSet()
+ {
+ ValidateConfiguration();
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ ///
+ /// Validates the configuration.
+ ///
+ protected virtual void ValidateConfiguration()
+ {
+ if (ServiceUri == null && ProxyType == null)
+ {
+ throw new ArgumentException("ServiceUri or ProxyType property is required.");
+ }
+ if (ServiceInterface == null)
+ {
+ throw new ArgumentException("The ServiceInterface property is required.");
+ }
+ if (!ServiceInterface.IsInterface)
+ {
+ throw new ArgumentException("ServiceInterface must be an interface");
+ }
+ if (WebServiceProxyBaseType.IsSealed)
+ {
+ throw new ArgumentException("Web service client proxy cannot be created for a sealed class [" + WebServiceProxyBaseType.FullName + "]");
+ }
+ }
+
+ ///
+ /// Generates the web service proxy type.
+ ///
+ protected virtual void GenerateProxy()
+ {
+ IProxyTypeBuilder builder;
+ if (ProxyType != null)
+ {
+ // Wrap .NET generated proxy class or another
+ builder = new WebServiceProxyProxyTypeBuilder();
+ builder.TargetType = ProxyType;
+ }
+ else
+ {
+ // Dynamically generates proxy class from WSDL
+ builder = new SoapHttpClientProxyTypeBuilder(
+ ServiceUri, GetWsDocuments(ServiceUri), BindingName);
+ builder.BaseType = WebServiceProxyBaseType;
+ }
+
+ builder.Interfaces = ReflectionUtils.ToInterfaceArray(ServiceInterface);
+ builder.TypeAttributes = TypeAttributes;
+ builder.MemberAttributes = MemberAttributes;
+
+ Type wrapper = builder.BuildProxyType();
+
+ proxyConstructor = wrapper.GetConstructor(Type.EmptyTypes);
+
+ #region Instrumentation
+
+ if (LOG.IsDebugEnabled)
+ {
+ if (ServiceUri != null)
+ {
+ LOG.Debug(
+ String.Format("Generated client proxy type [{0}] for web service [{1}]", wrapper.FullName,
+ ServiceUri.Description));
+ }
+ else if (ProxyType != null)
+ {
+ LOG.Debug(
+ String.Format("Generated client proxy type [{0}] for web service based on provided proxy type [{1}]", wrapper.FullName,
+ ProxyType.FullName));
+ }
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ ///
+ /// Gets XML Web Services documents from a Spring resource.
+ ///
+ private DiscoveryClientDocumentCollection GetWsDocuments(IResource resource)
+ {
+ try
+ {
+ if (ServiceUri is UrlResource ||
+ ServiceUri is FileSystemResource)
+ {
+ DiscoveryClientProtocol dcProtocol = new DiscoveryClientProtocol();
+ dcProtocol.AllowAutoRedirect = true;
+ dcProtocol.Credentials = CreateCredentials();
+ dcProtocol.Proxy = ConfigureProxy();
+ dcProtocol.DiscoverAny(resource.Uri.AbsoluteUri);
+ dcProtocol.ResolveAll();
+
+ return dcProtocol.Documents;
+ }
+ else
+ {
+ DiscoveryClientDocumentCollection dcdc = new DiscoveryClientDocumentCollection();
+ dcdc[resource.Description] = ServiceDescription.Read(resource.InputStream);
+ return dcdc;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new ArgumentException(String.Format("Couldn't retrieve the description of the web service located at '{0}'.", resource.Description), ex);
+ }
+ }
+
+ private IWebProxy ConfigureProxy()
+ {
+ IWebProxy webProxy = null;
+ if (ProxyUrl != null)
+ {
+ webProxy = new WebProxy(ProxyUrl);
+ }
+ if (ProxyCredential != null)
+ {
+ if (webProxy == null)
+ {
+#if !NET_2_0
+ webProxy = GlobalProxySelection.Select;
+#else
+ webProxy = WebRequest.DefaultWebProxy;
+#endif
+ }
+ webProxy.Credentials = ProxyCredential;
+ }
+
+ return webProxy;
+ }
+
+ private ICredentials CreateCredentials()
+ {
+ if (Credential != null)
+ {
+ CredentialCache credentialCache = new CredentialCache();
+
+ Uri wsUri = new Uri(ServiceUri.Uri.AbsoluteUri.Substring(0, ServiceUri.Uri.AbsoluteUri.Length - ServiceUri.Uri.AbsolutePath.Length));
+ IEnumerator enumerator = AuthenticationManager.RegisteredModules;
+ while (enumerator.MoveNext())
+ {
+ credentialCache.Add(wsUri, ((IAuthenticationModule)enumerator.Current).AuthenticationType, Credential);
+ }
+
+ return credentialCache;
+ }
+ else
+ {
+ return CredentialCache.DefaultCredentials;
+ }
+ }
+
+ #endregion
+
+ #region SoapHttpClientProxyTypeBuilder inner class implementation
+
+ ///
+ /// Proxy type builder that can be used to create a proxy for
+ /// derived classes.
+ ///
+ private sealed class SoapHttpClientProxyTypeBuilder : AbstractProxyTypeBuilder
+ {
+ #region Logging
+
+ private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(SoapHttpClientProxyTypeBuilder));
+
+ #endregion
+
+ #region Fields
+
+ // Binding/Type related
+ private IResource serviceUri;
+ private ServiceDescriptionCollection wsDescriptions;
+ private XmlSchemaImporter schemaImporter;
+ private Binding wsBinding;
+ private string wsUrl;
+
+ // Operation/Method related
+ private Operation operation;
+ private OperationBinding operationBinding;
+ private SoapOperationBinding soapOperationBinding;
+ private XmlMembersMapping inputMembersMapping;
+ private XmlMembersMapping outputMembersMapping;
+
+ #endregion
+
+ #region Constructor(s) / Destructor
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ /// The URI that contains the Web Service meta info (WSDL).
+ /// The XML Web Service documents to use to create the proxy.
+ /// The name of the Web Service binding to use.
+ public SoapHttpClientProxyTypeBuilder(IResource serviceUri,
+ DiscoveryClientDocumentCollection wsDocuments, string bindingName)
+ {
+ this.serviceUri = serviceUri;
+
+ Name = "SoapHttpClientProxy";
+ ProxyTargetAttributes = false;
+
+ Initialize(wsDocuments, bindingName);
+ }
+
+ #endregion
+
+ #region IProxyTypeBuilder Members
+
+ ///
+ /// Creates the proxy type.
+ ///
+ /// The generated proxy class.
+ public override Type BuildProxyType()
+ {
+ if (Interfaces == null || Interfaces.Length == 0)
+ {
+ throw new ArgumentException(
+ "Web service client proxy must implement at least one interface.");
+ }
+
+ TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
+
+ // apply custom attributes to the proxy type.
+ ApplyTypeAttributes(typeBuilder, TargetType);
+
+ // create constructors
+ ImplementConstructors(typeBuilder);
+
+ // implement service interfaces
+ foreach (Type intf in Interfaces)
+ {
+ ImplementInterface(typeBuilder,
+ new SoapHttpClientProxyMethodBuilder(typeBuilder, this),
+ intf, TargetType);
+ }
+
+ return typeBuilder.CreateType();
+ }
+
+ #endregion
+
+ #region IProxyTypeGenerator Members
+
+ ///
+ /// Generates the IL instructions that pushes
+ /// the target instance on which calls should be delegated to.
+ ///
+ /// The IL generator to use.
+ public override void PushTarget(ILGenerator il)
+ {
+ PushProxy(il);
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ ///
+ /// Implements constructors for the proxy class.
+ ///
+ ///
+ /// The to use.
+ ///
+ protected override void ImplementConstructors(TypeBuilder builder)
+ {
+ MethodAttributes attributes = MethodAttributes.Public |
+ MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+ MethodAttributes.RTSpecialName;
+ ConstructorBuilder cb = builder.DefineConstructor(attributes,
+ CallingConventions.Standard, Type.EmptyTypes);
+
+ ILGenerator il = cb.GetILGenerator();
+
+ PushProxy(il);
+ il.Emit(OpCodes.Call, this.BaseType.GetConstructor(Type.EmptyTypes));
+
+ // Set Url Property
+ PushProxy(il);
+ il.Emit(OpCodes.Ldstr, this.wsUrl);
+ il.Emit(OpCodes.Call, this.BaseType.GetMethod("set_Url", BindingFlags.Public | BindingFlags.Instance));
+
+ il.Emit(OpCodes.Ret);
+ }
+
+ protected override void ApplyMethodAttributes(
+ MethodBuilder methodBuilder, MethodInfo targetMethod)
+ {
+ MoveToMethod(targetMethod);
+
+ base.ApplyMethodAttributes(methodBuilder, targetMethod);
+ }
+
+ protected override IList GetTypeAttributes(Type type)
+ {
+ IList attrs = base.GetTypeAttributes(type);
+
+ // Add the WebServiceBindingAttribute
+ attrs.Add(CreateWebServiceBindingAttribute(this.wsBinding));
+
+ return attrs;
+ }
+
+ protected override IList GetMethodAttributes(MethodInfo method)
+ {
+ IList attrs = base.GetMethodAttributes(method);
+
+ // Add the SoapMethodAttribute
+ attrs.Add(CreateSoapMethodAttribute(
+ operation, operationBinding, soapOperationBinding, inputMembersMapping, outputMembersMapping));
+
+ return attrs;
+ }
+
+#if NET_2_0
+ protected override IList GetMethodReturnTypeAttributes(MethodInfo method)
+ {
+ IList attrs = base.GetMethodReturnTypeAttributes(method);
+
+ // Add the XmlElementAttribute if needed
+ if (operation.Messages.Output != null)
+ {
+ if (method.ReturnType != typeof(void))
+ {
+ if (outputMembersMapping.Count > 0)
+ {
+ XmlMemberMapping outMemberMapping = outputMembersMapping[0];
+ bool useMemberName = (outMemberMapping.MemberName != operation.Name + "Result");
+ bool useNamespace = outMemberMapping.Namespace != outputMembersMapping.Namespace;
+ if (useMemberName || useNamespace)
+ {
ReflectionUtils.CustomAttributeBuilderBuilder cabb;
if (outMemberMapping.TypeName.StartsWith ("ArrayOf", StringComparison.Ordinal))
{
cabb = new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(XmlArrayAttribute));
- }
+ }
else
{
cabb = new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(XmlElementAttribute));
- }
- if (useMemberName)
- {
- cabb.AddPropertyValue("ElementName", outMemberMapping.MemberName);
- }
- if (useNamespace)
- {
- cabb.AddPropertyValue("Namespace", outMemberMapping.Namespace);
- }
-
- attrs.Add(cabb.Build());
- }
- }
- }
- }
-
- return attrs;
- }
-#endif
-/*
- protected override IList GetMethodParameterAttributes(MethodInfo method, ParameterInfo paramInfo)
- {
- IList attrs = base.GetMethodParameterAttributes(method, paramInfo);
-
- // Add the XmlElementAttribute if needed
- XmlMemberMapping inMemberMapping = inputMembersMapping[paramInfo.Position];
- if (inMemberMapping.Namespace != inputMembersMapping.Namespace)
- {
- CustomAttributeBuilderBuilder cabb =
- new CustomAttributeBuilderBuilder(typeof(XmlElementAttribute));
- cabb.AddPropertyValue("Namespace", inMemberMapping.Namespace);
-
- attrs.Add(cabb.Build());
- }
-
- return attrs;
- }
-*/
-
- #endregion
-
- #region Private Methods
-
- private void Initialize(DiscoveryClientDocumentCollection wsDocuments, string bindingName)
- {
- // Service descriptions
- this.wsDescriptions = new ServiceDescriptionCollection();
- XmlSchemas schemas = new XmlSchemas();
- foreach (DictionaryEntry entry in wsDocuments)
- {
- if (entry.Value is ServiceDescription)
- {
- this.wsDescriptions.Add((ServiceDescription)entry.Value);
- }
- if (entry.Value is XmlSchema)
- {
- schemas.Add((XmlSchema)entry.Value);
- }
- }
-
- // XmlSchemaImporter
- foreach (ServiceDescription serviceDescription in this.wsDescriptions)
- {
- foreach (XmlSchema schema in serviceDescription.Types.Schemas)
- {
- if (schemas[schema.TargetNamespace] == null)
- {
- schemas.Add(schema);
- }
- }
- }
- this.schemaImporter = new XmlSchemaImporter(schemas);
-
- this.wsBinding = GetWsBinding(this.wsDescriptions, bindingName);
- this.wsUrl = GetWsUrl(this.wsDescriptions, this.wsBinding);
- }
-
- ///
- /// Search and returns the binding for the specified name.
- ///
- private Binding GetWsBinding(ServiceDescriptionCollection serviceDescriptions, string bindingName)
- {
- if (bindingName != null)
- {
- // Search for a specific binding
- foreach (ServiceDescription description in serviceDescriptions)
- {
- foreach (Binding binding in description.Bindings)
- {
- if (binding.Name == bindingName)
- {
- return binding;
- }
- }
- }
- throw new ApplicationException(String.Format("Binding '{0}' does not exist in the WSDL document located at '{1}'", bindingName, this.serviceUri.Description));
- }
- else
- {
- // Use the first one
- foreach (ServiceDescription description in serviceDescriptions)
- {
- foreach (Binding binding in description.Bindings)
- {
- #region Instrumentation
-
- if (LOG.IsInfoEnabled)
- {
- LOG.Info(String.Format("The binding '{0}', found in the WSDL document located at '{1}', will be use.", binding.Name, this.serviceUri.Description));
- }
-
- #endregion
-
- return binding;
- }
- }
- throw new ApplicationException(String.Format("No bindings exists in the WSDL document located at '{0}'", this.serviceUri.Description));
- }
- }
-
- ///
- /// Search and returns the url for the specified binding.
- ///
- private string GetWsUrl(ServiceDescriptionCollection serviceDescriptions, Binding binding)
- {
- foreach (ServiceDescription description in serviceDescriptions)
- {
- foreach (Service service in description.Services)
- {
- foreach (Port port in service.Ports)
- {
- if (port.Binding.Name == binding.Name)
- {
- SoapAddressBinding soapAddress = (SoapAddressBinding)port.Extensions.Find(typeof(SoapAddressBinding));
- return soapAddress.Location;
- }
- }
- }
- }
- throw new ApplicationException(String.Format("No SoapAddressBinding has been found for binding '{0}' in the WSDL document located at '{1}'.", binding.Name, serviceUri));
- }
-
- ///
- /// Search and returns the operation that matches the specified method.
- ///
- private Operation GetOperation(ServiceDescriptionCollection descriptions, Binding binding, MethodInfo method)
- {
- PortType portType = descriptions.GetPortType(binding.Type);
- foreach (Operation operation in portType.Operations)
- {
- if (operation.Name == method.Name)
- {
- return operation;
- }
- }
- throw new ApplicationException(String.Format("No Operation has been found for the method '{0}' in the WSDL document located at '{1}'.", method.Name, serviceUri.Description));
- }
-
- ///
- /// Search and returns the OperationBinding that matches the specified Operation.
- ///
- private OperationBinding GetOperationBinding(Operation operation, Binding binding)
- {
- foreach (OperationBinding operationBinding in binding.Operations)
- {
- if (operation.IsBoundBy(operationBinding))
- {
- return operationBinding;
- }
- }
- throw new ApplicationException(String.Format("No OperationBinding matches the Operation '{0}' in the WSDL document located at '{2}'.", operation.Name, this.serviceUri.Description));
- }
-
- ///
- /// Search and returns the type mapping between method parameters/return value
- /// and the element parts of a literal-use SOAP message.
- ///
- private XmlMembersMapping GetMembersMapping(string messageName, MessagePartCollection messageParts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle)
- {
-#if NET_2_0
- if (soapBindingStyle == SoapBindingStyle.Rpc)
- {
- SoapSchemaMember[] soapSchemaMembers = new SoapSchemaMember[messageParts.Count];
- for (int i = 0; i < messageParts.Count; i++)
- {
- SoapSchemaMember ssm = new SoapSchemaMember();
- ssm.MemberName = messageParts[i].Name;
- ssm.MemberType = messageParts[i].Type;
- soapSchemaMembers[i] = ssm;
- }
- return this.schemaImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, soapSchemaMembers);
- }
- else
- {
- return this.schemaImporter.ImportMembersMapping(messageParts[0].Element);
- }
-#else
- return this.schemaImporter.ImportMembersMapping(messageParts[0].Element);
-#endif
- }
-
- private void MoveToMethod(MethodInfo targetMethod)
- {
- operation = GetOperation(this.wsDescriptions, this.wsBinding, targetMethod);
- operationBinding = GetOperationBinding(operation, this.wsBinding);
- soapOperationBinding = (SoapOperationBinding)operationBinding.Extensions.Find(typeof(SoapOperationBinding));
-
- string inputMessageName = (!StringUtils.IsNullOrEmpty(operationBinding.Input.Name) && (soapOperationBinding.Style != SoapBindingStyle.Rpc)) ? operationBinding.Input.Name : operation.Name;
- SoapBodyBinding inputSoapBodyBinding = (SoapBodyBinding)operationBinding.Input.Extensions.Find(typeof(SoapBodyBinding));
-
-#if !NET_2_0
- if (soapOperationBinding.Style == SoapBindingStyle.Rpc &&
- inputSoapBodyBinding.Use == SoapBindingUse.Literal)
- {
- throw new NotSupportedException("rpc-literal SOAP messages are not supported on .NET Framework 1.1");
- }
-#endif
- if (inputSoapBodyBinding.Use != SoapBindingUse.Literal)
- {
- throw new NotSupportedException("WebServiceProxyFactory only supports document-literal and rpc-literal SOAP messages to conform to WS-I Basic Profiles.");
- }
-
- Message inputMessage = this.wsDescriptions.GetMessage(operation.Messages.Input.Message);
- inputMembersMapping = GetMembersMapping(inputMessageName, inputMessage.Parts, inputSoapBodyBinding, soapOperationBinding.Style);
-
- outputMembersMapping = null;
- if (operation.Messages.Output != null)
- {
- string outputMessageName = (!StringUtils.IsNullOrEmpty(operationBinding.Output.Name) && (soapOperationBinding.Style != SoapBindingStyle.Rpc)) ? operationBinding.Output.Name : (operation.Name + "Response");
- SoapBodyBinding outputSoapBodyBinding = (SoapBodyBinding)operationBinding.Output.Extensions.Find(typeof(SoapBodyBinding));
- Message outputMessage = this.wsDescriptions.GetMessage(operation.Messages.Output.Message);
- outputMembersMapping = GetMembersMapping(outputMessageName, outputMessage.Parts, outputSoapBodyBinding, soapOperationBinding.Style);
- }
- }
-
- ///
- /// Creates a that should be applied to proxy type.
- ///
- private CustomAttributeBuilder CreateWebServiceBindingAttribute(Binding wsBinding)
- {
- ReflectionUtils.CustomAttributeBuilderBuilder cabb =
- new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(WebServiceBindingAttribute));
-
- cabb.AddContructorArgument(this.wsBinding.Name);
- cabb.AddPropertyValue("Namespace", this.wsBinding.ServiceDescription.TargetNamespace);
-
- return cabb.Build();
- }
-
-#if !NET_2_0
- private static readonly PropertyInfo XmlMembersMapping_ElementName =
- typeof(XmlMembersMapping).GetProperty("ElementName");
-
- private static readonly PropertyInfo XmlMembersMapping_Namespace =
- typeof(XmlMembersMapping).GetProperty("Namespace");
-#endif
-
- ///
- /// Creates a or a
- /// that should be applied to proxy method.
- ///
- private static CustomAttributeBuilder CreateSoapMethodAttribute(Operation operation,
- OperationBinding operationBinding, SoapOperationBinding soapOperationBinding,
- XmlMembersMapping inputMembersMapping, XmlMembersMapping outputMembersMapping)
- {
- ReflectionUtils.CustomAttributeBuilderBuilder cabb;
-
-#if !NET_2_0
- // Access XmlMembersMapping.ElementName and .Namespace property using reflection [SPRNET-520]
- string inputMembersMappingElementName = XmlMembersMapping_ElementName.GetValue(inputMembersMapping, null) as string;
- string inputMembersMappingNamespace = XmlMembersMapping_Namespace.GetValue(inputMembersMapping, null) as string;
-#else
- string inputMembersMappingElementName = inputMembersMapping.ElementName;
- string inputMembersMappingNamespace = inputMembersMapping.Namespace;
-#endif
-
- if (soapOperationBinding.Style == SoapBindingStyle.Rpc)
- {
- cabb = new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(SoapRpcMethodAttribute));
- }
- else
- {
- cabb = new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(SoapDocumentMethodAttribute));
- cabb.AddPropertyValue("ParameterStyle", SoapParameterStyle.Wrapped);
- }
-
- cabb.AddContructorArgument(soapOperationBinding.SoapAction);
-
-#if NET_2_0
- cabb.AddPropertyValue("Use", SoapBindingUse.Literal);
-#else
- if (soapOperationBinding.Style != SoapBindingStyle.Rpc)
- {
- cabb.AddPropertyValue("Use", SoapBindingUse.Literal);
- }
-#endif
-
- if (inputMembersMappingElementName.Length > 0 &&
- inputMembersMappingElementName != operation.Name)
- {
- cabb.AddPropertyValue("RequestElementName", inputMembersMappingElementName);
- }
-
- if (inputMembersMappingNamespace != null)
- {
- cabb.AddPropertyValue("RequestNamespace", inputMembersMappingNamespace);
- }
-
- if (outputMembersMapping == null)
- {
- cabb.AddPropertyValue("OneWay", true);
- }
- else
- {
-#if !NET_2_0
- // Access XmlMembersMapping.ElementName and .Namespace property using reflection [SPRNET-520]
- string outputMembersMappingElementName = XmlMembersMapping_ElementName.GetValue(outputMembersMapping, null) as string;
- string outputMembersMappingNamespace = XmlMembersMapping_Namespace.GetValue(outputMembersMapping, null) as string;
-#else
- string outputMembersMappingElementName = outputMembersMapping.ElementName;
- string outputMembersMappingNamespace = outputMembersMapping.Namespace;
-#endif
- if (outputMembersMappingElementName.Length > 0 &&
- outputMembersMappingElementName != (operation.Name + "Response"))
- {
- cabb.AddPropertyValue("ResponseElementName", outputMembersMappingElementName);
- }
-
- if (outputMembersMappingNamespace != null)
- {
- cabb.AddPropertyValue("ResponseNamespace", outputMembersMappingNamespace);
- }
- }
-
- return cabb.Build();
- }
-
- #endregion
-
- #region SoapHttpClientProxyMethodBuilder inner class implementation
-
- ///
- /// Proxy method builder that can be used to create a proxy method
- /// for web services operation invocation.
- ///
- private sealed class SoapHttpClientProxyMethodBuilder : AbstractProxyMethodBuilder
- {
- #region Fields
-
- private static readonly MethodInfo Invoke =
- typeof(SoapHttpClientProtocol).GetMethod("Invoke", BindingFlags.NonPublic | BindingFlags.Instance);
-
- #endregion
-
- #region Constructor(s) / Destructor
-
- ///
- /// Creates a new instance of the method builder.
- ///
- /// The type builder to use.
- ///
- /// The implementation to use.
- ///
- public SoapHttpClientProxyMethodBuilder(
- TypeBuilder typeBuilder, IProxyTypeGenerator proxyGenerator)
- : base(typeBuilder, proxyGenerator, false)
- {
- }
-
- #endregion
-
- #region Protected Methods
-
- ///
- /// Generates the proxy method.
- ///
- /// The IL generator to use.
- /// The method to proxy.
- ///
- /// The interface definition of the method, if applicable.
- ///
- protected override void GenerateMethod(
- ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
- {
- // In Parameters
- ArrayList inParams = new ArrayList();
- // Ref or Out Parameters
- ArrayList refOutParams = new ArrayList();
-
- foreach (ParameterInfo paramInfo in interfaceMethod.GetParameters())
- {
- if (paramInfo.IsRetval || paramInfo.IsOut)
- {
- refOutParams.Add(paramInfo);
- }
- else
- {
- inParams.Add(paramInfo);
- }
- }
-
- proxyGenerator.PushTarget(il);
-
- // Parameter #1
- il.Emit(OpCodes.Ldstr, interfaceMethod.Name);
-
- // Parameter #2
- LocalBuilder parameters = il.DeclareLocal(typeof(Object[]));
- il.Emit(OpCodes.Ldc_I4, inParams.Count);
- il.Emit(OpCodes.Newarr, typeof(Object));
- il.Emit(OpCodes.Stloc, parameters);
-
- int paramIndex = 0;
- foreach (ParameterInfo paramInfo in inParams)
- {
- il.Emit(OpCodes.Ldloc, parameters);
- il.Emit(OpCodes.Ldc_I4, paramIndex);
- il.Emit(OpCodes.Ldarg, paramInfo.Position + 1);
- if (paramInfo.ParameterType.IsValueType)
- {
- il.Emit(OpCodes.Box, paramInfo.ParameterType);
- }
- il.Emit(OpCodes.Stelem_Ref);
-
- paramIndex++;
- }
-
- il.Emit(OpCodes.Ldloc, parameters);
-
- // Call Invoke method and save result
- LocalBuilder results = il.DeclareLocal(typeof(Object[]));
- il.EmitCall(OpCodes.Callvirt, Invoke, null);
- il.Emit(OpCodes.Stloc, results);
-
- int resultIndex = (interfaceMethod.ReturnType == typeof(void) ? 0 : 1);
- foreach (ParameterInfo paramInfo in refOutParams)
- {
- il.Emit(OpCodes.Ldarg, paramInfo.Position + 1);
- il.Emit(OpCodes.Ldloc, results);
-
- // Cast / Unbox the return value
- il.Emit(OpCodes.Ldc_I4, resultIndex);
- il.Emit(OpCodes.Ldelem_Ref);
-
- Type elementType = paramInfo.ParameterType.GetElementType();
- if (elementType.IsValueType)
- {
- il.Emit(OpCodes.Unbox, elementType);
- il.Emit(OpCodes.Ldobj, elementType);
- il.Emit(OpCodes.Stobj, elementType);
- }
- else
- {
- il.Emit(OpCodes.Castclass, elementType);
- il.Emit(OpCodes.Stind_Ref);
- }
-
- resultIndex++;
- }
-
- if (interfaceMethod.ReturnType != typeof(void))
- {
- il.Emit(OpCodes.Ldloc, results);
-
- // Cast / Unbox the return value
- il.Emit(OpCodes.Ldc_I4_0);
- il.Emit(OpCodes.Ldelem_Ref);
- if (interfaceMethod.ReturnType.IsValueType)
- {
- il.Emit(OpCodes.Unbox, interfaceMethod.ReturnType);
- il.Emit(OpCodes.Ldobj, interfaceMethod.ReturnType);
- }
- else
- {
- il.Emit(OpCodes.Castclass, interfaceMethod.ReturnType);
- }
- }
- }
-
- #endregion
- }
-
- #endregion
- }
-
- #endregion
-
- #region WebServiceProxyProxyTypeBuilder inner class implementation
-
- ///
- /// Proxy type builder that can be used to create a proxy for
- /// .Net-generated proxy class that can be safely cast to a service interface.
- ///
- private sealed class WebServiceProxyProxyTypeBuilder : InheritanceProxyTypeBuilder
- {
- #region Constructor(s) / Destructor
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- public WebServiceProxyProxyTypeBuilder()
- {
- this.Name = "WebServiceProxyProxy";
- }
-
- #endregion
-
- #region Protected Methods
-
- ///
- /// Gets the mapping of the interface to proxy
- /// into the actual methods on the target type
- /// that does not need to implement that interface.
- ///
- ///
- ///
- /// As the proxy type does not implement the interface,
- /// we try to find matching methods.
- ///
- ///
- ///
- /// The of the target object.
- ///
- /// The interface to implement.
- ///
- /// An interface mapping for the interface to proxy.
- ///
- protected override InterfaceMapping GetInterfaceMapping(
- Type targetType, Type intf)
- {
- InterfaceMapping mapping;
-
- mapping.TargetType = targetType;
- mapping.InterfaceType = intf;
- mapping.InterfaceMethods = intf.GetMethods();
- mapping.TargetMethods = ReflectionUtils.GetMatchingMethods(
- targetType, mapping.InterfaceMethods, true);
-
- return mapping;
- }
-
- #endregion
- }
-
- #endregion
- }
+ }
+ if (useMemberName)
+ {
+ cabb.AddPropertyValue("ElementName", outMemberMapping.MemberName);
+ }
+ if (useNamespace)
+ {
+ cabb.AddPropertyValue("Namespace", outMemberMapping.Namespace);
+ }
+
+ attrs.Add(cabb.Build());
+ }
+ }
+ }
+ }
+
+ return attrs;
+ }
+#endif
+/*
+ protected override IList GetMethodParameterAttributes(MethodInfo method, ParameterInfo paramInfo)
+ {
+ IList attrs = base.GetMethodParameterAttributes(method, paramInfo);
+
+ // Add the XmlElementAttribute if needed
+ XmlMemberMapping inMemberMapping = inputMembersMapping[paramInfo.Position];
+ if (inMemberMapping.Namespace != inputMembersMapping.Namespace)
+ {
+ CustomAttributeBuilderBuilder cabb =
+ new CustomAttributeBuilderBuilder(typeof(XmlElementAttribute));
+ cabb.AddPropertyValue("Namespace", inMemberMapping.Namespace);
+
+ attrs.Add(cabb.Build());
+ }
+
+ return attrs;
+ }
+*/
+
+ #endregion
+
+ #region Private Methods
+
+ private void Initialize(DiscoveryClientDocumentCollection wsDocuments, string bindingName)
+ {
+ // Service descriptions
+ this.wsDescriptions = new ServiceDescriptionCollection();
+ XmlSchemas schemas = new XmlSchemas();
+ foreach (DictionaryEntry entry in wsDocuments)
+ {
+ if (entry.Value is ServiceDescription)
+ {
+ this.wsDescriptions.Add((ServiceDescription)entry.Value);
+ }
+ if (entry.Value is XmlSchema)
+ {
+ schemas.Add((XmlSchema)entry.Value);
+ }
+ }
+
+ // XmlSchemaImporter
+ foreach (ServiceDescription serviceDescription in this.wsDescriptions)
+ {
+ foreach (XmlSchema schema in serviceDescription.Types.Schemas)
+ {
+ if (schemas[schema.TargetNamespace] == null)
+ {
+ schemas.Add(schema);
+ }
+ }
+ }
+ this.schemaImporter = new XmlSchemaImporter(schemas);
+
+ this.wsBinding = GetWsBinding(this.wsDescriptions, bindingName);
+ this.wsUrl = GetWsUrl(this.wsDescriptions, this.wsBinding);
+ }
+
+ ///
+ /// Search and returns the binding for the specified name.
+ ///
+ private Binding GetWsBinding(ServiceDescriptionCollection serviceDescriptions, string bindingName)
+ {
+ if (bindingName != null)
+ {
+ // Search for a specific binding
+ foreach (ServiceDescription description in serviceDescriptions)
+ {
+ foreach (Binding binding in description.Bindings)
+ {
+ if (binding.Name == bindingName)
+ {
+ return binding;
+ }
+ }
+ }
+ throw new ApplicationException(String.Format("Binding '{0}' does not exist in the WSDL document located at '{1}'", bindingName, this.serviceUri.Description));
+ }
+ else
+ {
+ // Use the first one
+ foreach (ServiceDescription description in serviceDescriptions)
+ {
+ foreach (Binding binding in description.Bindings)
+ {
+ #region Instrumentation
+
+ if (LOG.IsInfoEnabled)
+ {
+ LOG.Info(String.Format("The binding '{0}', found in the WSDL document located at '{1}', will be use.", binding.Name, this.serviceUri.Description));
+ }
+
+ #endregion
+
+ return binding;
+ }
+ }
+ throw new ApplicationException(String.Format("No bindings exists in the WSDL document located at '{0}'", this.serviceUri.Description));
+ }
+ }
+
+ ///
+ /// Search and returns the url for the specified binding.
+ ///
+ private string GetWsUrl(ServiceDescriptionCollection serviceDescriptions, Binding binding)
+ {
+ foreach (ServiceDescription description in serviceDescriptions)
+ {
+ foreach (Service service in description.Services)
+ {
+ foreach (Port port in service.Ports)
+ {
+ if (port.Binding.Name == binding.Name)
+ {
+ SoapAddressBinding soapAddress = (SoapAddressBinding)port.Extensions.Find(typeof(SoapAddressBinding));
+ return soapAddress.Location;
+ }
+ }
+ }
+ }
+ throw new ApplicationException(String.Format("No SoapAddressBinding has been found for binding '{0}' in the WSDL document located at '{1}'.", binding.Name, serviceUri));
+ }
+
+ ///
+ /// Search and returns the operation that matches the specified method.
+ ///
+ private Operation GetOperation(ServiceDescriptionCollection descriptions, Binding binding, MethodInfo method)
+ {
+ PortType portType = descriptions.GetPortType(binding.Type);
+ foreach (Operation operation in portType.Operations)
+ {
+ if (operation.Name == method.Name)
+ {
+ return operation;
+ }
+ }
+ throw new ApplicationException(String.Format("No Operation has been found for the method '{0}' in the WSDL document located at '{1}'.", method.Name, serviceUri.Description));
+ }
+
+ ///
+ /// Search and returns the OperationBinding that matches the specified Operation.
+ ///
+ private OperationBinding GetOperationBinding(Operation operation, Binding binding)
+ {
+ foreach (OperationBinding operationBinding in binding.Operations)
+ {
+ if (operation.IsBoundBy(operationBinding))
+ {
+ return operationBinding;
+ }
+ }
+ throw new ApplicationException(String.Format("No OperationBinding matches the Operation '{0}' in the WSDL document located at '{2}'.", operation.Name, this.serviceUri.Description));
+ }
+
+ ///
+ /// Search and returns the type mapping between method parameters/return value
+ /// and the element parts of a literal-use SOAP message.
+ ///
+ private XmlMembersMapping GetMembersMapping(string messageName, MessagePartCollection messageParts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle)
+ {
+#if NET_2_0
+ if (soapBindingStyle == SoapBindingStyle.Rpc)
+ {
+ SoapSchemaMember[] soapSchemaMembers = new SoapSchemaMember[messageParts.Count];
+ for (int i = 0; i < messageParts.Count; i++)
+ {
+ SoapSchemaMember ssm = new SoapSchemaMember();
+ ssm.MemberName = messageParts[i].Name;
+ ssm.MemberType = messageParts[i].Type;
+ soapSchemaMembers[i] = ssm;
+ }
+ return this.schemaImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, soapSchemaMembers);
+ }
+ else
+ {
+ return this.schemaImporter.ImportMembersMapping(messageParts[0].Element);
+ }
+#else
+ return this.schemaImporter.ImportMembersMapping(messageParts[0].Element);
+#endif
+ }
+
+ private void MoveToMethod(MethodInfo targetMethod)
+ {
+ operation = GetOperation(this.wsDescriptions, this.wsBinding, targetMethod);
+ operationBinding = GetOperationBinding(operation, this.wsBinding);
+ soapOperationBinding = (SoapOperationBinding)operationBinding.Extensions.Find(typeof(SoapOperationBinding));
+
+ string inputMessageName = (!StringUtils.IsNullOrEmpty(operationBinding.Input.Name) && (soapOperationBinding.Style != SoapBindingStyle.Rpc)) ? operationBinding.Input.Name : operation.Name;
+ SoapBodyBinding inputSoapBodyBinding = (SoapBodyBinding)operationBinding.Input.Extensions.Find(typeof(SoapBodyBinding));
+
+#if !NET_2_0
+ if (soapOperationBinding.Style == SoapBindingStyle.Rpc &&
+ inputSoapBodyBinding.Use == SoapBindingUse.Literal)
+ {
+ throw new NotSupportedException("rpc-literal SOAP messages are not supported on .NET Framework 1.1");
+ }
+#endif
+ if (inputSoapBodyBinding.Use != SoapBindingUse.Literal)
+ {
+ throw new NotSupportedException("WebServiceProxyFactory only supports document-literal and rpc-literal SOAP messages to conform to WS-I Basic Profiles.");
+ }
+
+ Message inputMessage = this.wsDescriptions.GetMessage(operation.Messages.Input.Message);
+ inputMembersMapping = GetMembersMapping(inputMessageName, inputMessage.Parts, inputSoapBodyBinding, soapOperationBinding.Style);
+
+ outputMembersMapping = null;
+ if (operation.Messages.Output != null)
+ {
+ string outputMessageName = (!StringUtils.IsNullOrEmpty(operationBinding.Output.Name) && (soapOperationBinding.Style != SoapBindingStyle.Rpc)) ? operationBinding.Output.Name : (operation.Name + "Response");
+ SoapBodyBinding outputSoapBodyBinding = (SoapBodyBinding)operationBinding.Output.Extensions.Find(typeof(SoapBodyBinding));
+ Message outputMessage = this.wsDescriptions.GetMessage(operation.Messages.Output.Message);
+ outputMembersMapping = GetMembersMapping(outputMessageName, outputMessage.Parts, outputSoapBodyBinding, soapOperationBinding.Style);
+ }
+ }
+
+ ///
+ /// Creates a that should be applied to proxy type.
+ ///
+ private CustomAttributeBuilder CreateWebServiceBindingAttribute(Binding wsBinding)
+ {
+ ReflectionUtils.CustomAttributeBuilderBuilder cabb =
+ new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(WebServiceBindingAttribute));
+
+ cabb.AddContructorArgument(this.wsBinding.Name);
+ cabb.AddPropertyValue("Namespace", this.wsBinding.ServiceDescription.TargetNamespace);
+
+ return cabb.Build();
+ }
+
+#if !NET_2_0
+ private static readonly PropertyInfo XmlMembersMapping_ElementName =
+ typeof(XmlMembersMapping).GetProperty("ElementName");
+
+ private static readonly PropertyInfo XmlMembersMapping_Namespace =
+ typeof(XmlMembersMapping).GetProperty("Namespace");
+#endif
+
+ ///
+ /// Creates a or a
+ /// that should be applied to proxy method.
+ ///
+ private static CustomAttributeBuilder CreateSoapMethodAttribute(Operation operation,
+ OperationBinding operationBinding, SoapOperationBinding soapOperationBinding,
+ XmlMembersMapping inputMembersMapping, XmlMembersMapping outputMembersMapping)
+ {
+ ReflectionUtils.CustomAttributeBuilderBuilder cabb;
+
+#if !NET_2_0
+ // Access XmlMembersMapping.ElementName and .Namespace property using reflection [SPRNET-520]
+ string inputMembersMappingElementName = XmlMembersMapping_ElementName.GetValue(inputMembersMapping, null) as string;
+ string inputMembersMappingNamespace = XmlMembersMapping_Namespace.GetValue(inputMembersMapping, null) as string;
+#else
+ string inputMembersMappingElementName = inputMembersMapping.ElementName;
+ string inputMembersMappingNamespace = inputMembersMapping.Namespace;
+#endif
+
+ if (soapOperationBinding.Style == SoapBindingStyle.Rpc)
+ {
+ cabb = new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(SoapRpcMethodAttribute));
+ }
+ else
+ {
+ cabb = new ReflectionUtils.CustomAttributeBuilderBuilder(typeof(SoapDocumentMethodAttribute));
+ cabb.AddPropertyValue("ParameterStyle", SoapParameterStyle.Wrapped);
+ }
+
+ cabb.AddContructorArgument(soapOperationBinding.SoapAction);
+
+#if NET_2_0
+ cabb.AddPropertyValue("Use", SoapBindingUse.Literal);
+#else
+ if (soapOperationBinding.Style != SoapBindingStyle.Rpc)
+ {
+ cabb.AddPropertyValue("Use", SoapBindingUse.Literal);
+ }
+#endif
+
+ if (inputMembersMappingElementName.Length > 0 &&
+ inputMembersMappingElementName != operation.Name)
+ {
+ cabb.AddPropertyValue("RequestElementName", inputMembersMappingElementName);
+ }
+
+ if (inputMembersMappingNamespace != null)
+ {
+ cabb.AddPropertyValue("RequestNamespace", inputMembersMappingNamespace);
+ }
+
+ if (outputMembersMapping == null)
+ {
+ cabb.AddPropertyValue("OneWay", true);
+ }
+ else
+ {
+#if !NET_2_0
+ // Access XmlMembersMapping.ElementName and .Namespace property using reflection [SPRNET-520]
+ string outputMembersMappingElementName = XmlMembersMapping_ElementName.GetValue(outputMembersMapping, null) as string;
+ string outputMembersMappingNamespace = XmlMembersMapping_Namespace.GetValue(outputMembersMapping, null) as string;
+#else
+ string outputMembersMappingElementName = outputMembersMapping.ElementName;
+ string outputMembersMappingNamespace = outputMembersMapping.Namespace;
+#endif
+ if (outputMembersMappingElementName.Length > 0 &&
+ outputMembersMappingElementName != (operation.Name + "Response"))
+ {
+ cabb.AddPropertyValue("ResponseElementName", outputMembersMappingElementName);
+ }
+
+ if (outputMembersMappingNamespace != null)
+ {
+ cabb.AddPropertyValue("ResponseNamespace", outputMembersMappingNamespace);
+ }
+ }
+
+ return cabb.Build();
+ }
+
+ #endregion
+
+ #region SoapHttpClientProxyMethodBuilder inner class implementation
+
+ ///
+ /// Proxy method builder that can be used to create a proxy method
+ /// for web services operation invocation.
+ ///
+ private sealed class SoapHttpClientProxyMethodBuilder : AbstractProxyMethodBuilder
+ {
+ #region Fields
+
+ private static readonly MethodInfo Invoke =
+ typeof(SoapHttpClientProtocol).GetMethod("Invoke", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ #endregion
+
+ #region Constructor(s) / Destructor
+
+ ///
+ /// Creates a new instance of the method builder.
+ ///
+ /// The type builder to use.
+ ///
+ /// The implementation to use.
+ ///
+ public SoapHttpClientProxyMethodBuilder(
+ TypeBuilder typeBuilder, IProxyTypeGenerator proxyGenerator)
+ : base(typeBuilder, proxyGenerator, false)
+ {
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ ///
+ /// Generates the proxy method.
+ ///
+ /// The IL generator to use.
+ /// The method to proxy.
+ ///
+ /// The interface definition of the method, if applicable.
+ ///
+ protected override void GenerateMethod(
+ ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
+ {
+ // In Parameters
+ ArrayList inParams = new ArrayList();
+ // Ref or Out Parameters
+ ArrayList refOutParams = new ArrayList();
+
+ foreach (ParameterInfo paramInfo in interfaceMethod.GetParameters())
+ {
+ if (paramInfo.IsRetval || paramInfo.IsOut)
+ {
+ refOutParams.Add(paramInfo);
+ }
+ else
+ {
+ inParams.Add(paramInfo);
+ }
+ }
+
+ proxyGenerator.PushTarget(il);
+
+ // Parameter #1
+ il.Emit(OpCodes.Ldstr, interfaceMethod.Name);
+
+ // Parameter #2
+ LocalBuilder parameters = il.DeclareLocal(typeof(Object[]));
+ il.Emit(OpCodes.Ldc_I4, inParams.Count);
+ il.Emit(OpCodes.Newarr, typeof(Object));
+ il.Emit(OpCodes.Stloc, parameters);
+
+ int paramIndex = 0;
+ foreach (ParameterInfo paramInfo in inParams)
+ {
+ il.Emit(OpCodes.Ldloc, parameters);
+ il.Emit(OpCodes.Ldc_I4, paramIndex);
+ il.Emit(OpCodes.Ldarg, paramInfo.Position + 1);
+ if (paramInfo.ParameterType.IsValueType)
+ {
+ il.Emit(OpCodes.Box, paramInfo.ParameterType);
+ }
+ il.Emit(OpCodes.Stelem_Ref);
+
+ paramIndex++;
+ }
+
+ il.Emit(OpCodes.Ldloc, parameters);
+
+ // Call Invoke method and save result
+ LocalBuilder results = il.DeclareLocal(typeof(Object[]));
+ il.EmitCall(OpCodes.Callvirt, Invoke, null);
+ il.Emit(OpCodes.Stloc, results);
+
+ int resultIndex = (interfaceMethod.ReturnType == typeof(void) ? 0 : 1);
+ foreach (ParameterInfo paramInfo in refOutParams)
+ {
+ il.Emit(OpCodes.Ldarg, paramInfo.Position + 1);
+ il.Emit(OpCodes.Ldloc, results);
+
+ // Cast / Unbox the return value
+ il.Emit(OpCodes.Ldc_I4, resultIndex);
+ il.Emit(OpCodes.Ldelem_Ref);
+
+ Type elementType = paramInfo.ParameterType.GetElementType();
+ if (elementType.IsValueType)
+ {
+ il.Emit(OpCodes.Unbox, elementType);
+ il.Emit(OpCodes.Ldobj, elementType);
+ il.Emit(OpCodes.Stobj, elementType);
+ }
+ else
+ {
+ il.Emit(OpCodes.Castclass, elementType);
+ il.Emit(OpCodes.Stind_Ref);
+ }
+
+ resultIndex++;
+ }
+
+ if (interfaceMethod.ReturnType != typeof(void))
+ {
+ il.Emit(OpCodes.Ldloc, results);
+
+ // Cast / Unbox the return value
+ il.Emit(OpCodes.Ldc_I4_0);
+ il.Emit(OpCodes.Ldelem_Ref);
+ if (interfaceMethod.ReturnType.IsValueType)
+ {
+ il.Emit(OpCodes.Unbox, interfaceMethod.ReturnType);
+ il.Emit(OpCodes.Ldobj, interfaceMethod.ReturnType);
+ }
+ else
+ {
+ il.Emit(OpCodes.Castclass, interfaceMethod.ReturnType);
+ }
+ }
+ }
+
+ #endregion
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ #region WebServiceProxyProxyTypeBuilder inner class implementation
+
+ ///
+ /// Proxy type builder that can be used to create a proxy for
+ /// .Net-generated proxy class that can be safely cast to a service interface.
+ ///
+ private sealed class WebServiceProxyProxyTypeBuilder : InheritanceProxyTypeBuilder
+ {
+ #region Constructor(s) / Destructor
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ public WebServiceProxyProxyTypeBuilder()
+ {
+ this.Name = "WebServiceProxyProxy";
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ ///
+ /// Gets the mapping of the interface to proxy
+ /// into the actual methods on the target type
+ /// that does not need to implement that interface.
+ ///
+ ///
+ ///
+ /// As the proxy type does not implement the interface,
+ /// we try to find matching methods.
+ ///
+ ///
+ ///
+ /// The of the target object.
+ ///
+ /// The interface to implement.
+ ///
+ /// An interface mapping for the interface to proxy.
+ ///
+ protected override InterfaceMapping GetInterfaceMapping(
+ Type targetType, Type intf)
+ {
+ InterfaceMapping mapping;
+
+ mapping.TargetType = targetType;
+ mapping.InterfaceType = intf;
+ mapping.InterfaceMethods = intf.GetMethods();
+ mapping.TargetMethods = ReflectionUtils.GetMatchingMethods(
+ targetType, mapping.InterfaceMethods, true);
+
+ return mapping;
+ }
+
+ #endregion
+ }
+
+ #endregion
+ }
}
\ No newline at end of file