VSWCFServiceContractGenerator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Extensions / Compilation / WCFModel / VSWCFServiceContractGenerator.cs / 1305376 / VSWCFServiceContractGenerator.cs

                            //------------------------------------------------------------------------------ 
// 
//   Copyright (C) Microsoft Corporation. All Rights Reserved.
// 
//----------------------------------------------------------------------------- 

 
using System; 
using System.CodeDom;
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.Configuration;
using System.Globalization;
using System.Reflection; 
using System.Runtime.Serialization;
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Configuration;
using System.ServiceModel.Description; 
using System.Web.Services.Description;
using System.Xml;
using System.Xml.Schema;
using System.Security.Permissions; 
using System.Linq;
 
#if WEB_EXTENSIONS_CODE 
using System.Web.Resources;
#else 
using Microsoft.VSDesigner.Resources.Microsoft.VSDesigner;
#endif

/// 
/// The VSWCFServiceContractGenerator takes a SvcMap file and it's associated metadata,
/// imports the metadata using a WsdlImporter and System.ServiceModel.ServiceContractGenerator 
/// that are configured according to the options set in the SvcMap file 
///
using Debug = System.Diagnostics.Debug; 
using System.Security;

#if WEB_EXTENSIONS_CODE
namespace System.Web.Compilation.WCFModel 
#else
namespace Microsoft.VSDesigner.WCFModel 
#endif 
{
    ///  
    /// Proxy and configuration generator
    /// 
#if WEB_EXTENSIONS_CODE
    [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")] 
    // Transparency
    [SecurityCritical] 
    internal class VSWCFServiceContractGenerator 
#else
    // We only check for CLS compliant for the public version of this class since the 
    // compiler will complain about CLS compliance not being checked for non-public classes
    // Transparency
    [SecurityCritical]
    [CLSCompliant(true), PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")] 
    public class VSWCFServiceContractGenerator
#endif 
    { 

        #region Private backing fields 
        private const string VB_LANGUAGE_NAME = "vb";

        /// 
        /// Collection to hold all bindings generated by this generator 
        /// 
        private IEnumerable bindingCollection; 
 
        /// 
        /// Collection to hold all contracts generated by this generator 
        /// 
        private IEnumerable contractCollection;

        ///  
        /// Collection to hold all endpoints generated by this generator
        ///  
        private List serviceEndpointList; 

        ///  
        /// Map from service endpoint to the channel endpoint that was actually imported
        /// 
        private Dictionary serviceEndpointToChannelEndpointElementMap;
 
        /// 
        /// List of contract types generate by this generator 
        ///  
        private List proxyGeneratedContractTypes;
 
        /// 
        /// The target compile unit that contains the proxy and data contracts
        /// 
        private CodeCompileUnit targetCompileUnit; 

        ///  
        /// Configuration object that we inserterd bindings and endpoints from the 
        /// current service into. May be Null/Nothing.
        ///  
        private System.Configuration.Configuration targetConfiguration;

        /// 
        /// Errors encountered while generating the proxy 
        /// 
        private IEnumerable proxyGenerationErrors; 
 
        /// 
        /// Errors encountered while importing the metadata.. 
        /// 
        private IList importErrors;

        ///  
        /// Helper property that is added to Out parameters for VB
        ///  
        private static CodeAttributeDeclaration outAttribute; 

        ///  
        /// version number for 3.5 framework
        /// 
        private const int FRAMEWORK_VERSION_35 = 0x30005;
 
        /// 
        /// list of types which are new in the 3.5 framework. 
        ///  
        private static Type[] unsupportedTypesInFramework30 = new Type[] {
            typeof(DateTimeOffset), 
        };


        #endregion 

        #region Public read-only properties 
 
        /// 
        /// The collection of bindings generated by this generator 
        /// 
        /// 
        /// 
        ///  
        public IEnumerable BindingCollection
        { 
            get 
            {
                System.Diagnostics.Debug.Assert(bindingCollection != null); 
                return bindingCollection;
            }
        }
 
        /// 
        /// The collection of generated contract types 
        ///  
        public IEnumerable ProxyGeneratedContractTypes
        { 
            get
            {
                System.Diagnostics.Debug.Assert(proxyGeneratedContractTypes != null);
                return proxyGeneratedContractTypes; 
            }
        } 
 
        /// 
        /// The collection of errors encountered while generating the 
        /// proxy. For errors related to the metadata import, use the
        /// ImportErrors property
        /// 
        public IEnumerable ProxyGenerationErrors 
        {
            get 
            { 
                System.Diagnostics.Debug.Assert(proxyGenerationErrors != null);
                return proxyGenerationErrors; 
            }
        }

        ///  
        /// The collection of errors encountered while importing metadata.
        /// For errors related to the proxy and config generation, use the 
        /// ProxyGenerationErrors property 
        /// 
        public IEnumerable ImportErrors 
        {
            get
            {
                System.Diagnostics.Debug.Assert(importErrors != null); 
                return importErrors;
            } 
        } 

        ///  
        /// The collection of contracts imported by this generator
        /// 
        /// 
        ///  
        public IEnumerable ContractCollection
        { 
            get 
            {
                System.Diagnostics.Debug.Assert(contractCollection != null); 
                return contractCollection;
            }
        }
 
        /// 
        /// Collection of Endpoints in the service model generated by 
        /// this generator 
        /// 
        ///  
        /// 
        public IEnumerable EndpointCollection
        {
            get 
            {
                System.Diagnostics.Debug.Assert(serviceEndpointList != null); 
                return serviceEndpointList; 
            }
        } 

        /// 
        /// Map from service endpoints to its corresponding channel endpoint configuration
        /// element 
        /// 
        public Dictionary EndpointMap 
        { 
            get
            { 
                System.Diagnostics.Debug.Assert(serviceEndpointToChannelEndpointElementMap != null);
                return serviceEndpointToChannelEndpointElementMap;
            }
        } 

        ///  
        /// The configuratin into which we inject the bindings and endpoints. May be null/Nothing 
        /// if no target configuration was provided.
        ///  
        public System.Configuration.Configuration TargetConfiguration
        {
            get
            { 
                // Note: it is valid for this to be NULL. Caller beware!
                return targetConfiguration; 
            } 
        }
 
        /// 
        /// CodeCompileUnit containing the generated data contracts, service contracts
        /// and WCF client.
        ///  
        public CodeCompileUnit TargetCompileUnit
        { 
            get 
            {
                System.Diagnostics.Debug.Assert(targetCompileUnit != null); 
                return targetCompileUnit;
            }
        }
 
        #endregion
 
        ///  
        /// Cached instance of an Out attribute that we use to patch up
        /// the codegen for VB projects (the VB code generates out parameters 
        /// as ByRef)
        /// 
        private static CodeAttributeDeclaration OutAttribute
        { 
            get
            { 
                if (outAttribute == null) 
                {
                    outAttribute = new CodeAttributeDeclaration(typeof(System.Runtime.InteropServices.OutAttribute).FullName); 
                }
                return outAttribute;
            }
        } 

        ///  
        /// protected constructor to block creating instance directly. 
        /// 
        ///  
        /// 
        /// May be null
        /// 
        ///  
        /// 
        ///  
        ///  
        /// 
        protected VSWCFServiceContractGenerator( 
                List importErrors,
                CodeCompileUnit targetCompileUnit,
                System.Configuration.Configuration targetConfiguration,
                IEnumerable bindingCollection, 
                IEnumerable contractCollection,
                List serviceEndpointList, 
                Dictionary serviceEndpointToChannelEndpointElementMap, 
                List proxyGeneratedContractTypes,
                IEnumerable proxyGenerationErrors) 
        {
            if (importErrors == null) throw new ArgumentNullException("importErrors");
            if (targetCompileUnit == null) throw new ArgumentNullException("targetCompileUnit");
            // Please note - target configuration may be NULL 
            if (bindingCollection == null) throw new ArgumentNullException("bindingCollection");
            if (contractCollection == null) throw new ArgumentNullException("contractCollection"); 
            if (serviceEndpointList == null) throw new ArgumentNullException("serviceEndpointList"); 
            if (serviceEndpointToChannelEndpointElementMap == null) throw new ArgumentNullException("serviceEndpointToChannelEndpointElementMap");
            if (proxyGeneratedContractTypes == null) throw new ArgumentNullException("proxyGeneratedContractTypes"); 
            if (proxyGenerationErrors == null) throw new ArgumentNullException("proxyGenerationErrors");

            this.importErrors = importErrors;
            this.targetCompileUnit = targetCompileUnit; 
            this.targetConfiguration = targetConfiguration;
            this.bindingCollection = bindingCollection; 
            this.contractCollection = contractCollection; 
            this.serviceEndpointList = serviceEndpointList;
            this.serviceEndpointToChannelEndpointElementMap = serviceEndpointToChannelEndpointElementMap; 
            this.proxyGeneratedContractTypes = proxyGeneratedContractTypes;
            this.proxyGenerationErrors = proxyGenerationErrors;
        }
 
        /// 
        /// Factory method: generate code and return the resulting VSWCFServiceContractGenerator. 
        ///  
        /// 
        /// The SvcMapFile that lists the metadata and generation options for the service reference. 
        /// 
        /// 
        /// Configuration from which we are going to pick up WSDL and policy importer extensions as well
        /// as custom MEX bindings for metadata download. May be Null/Nothing. 
        /// 
        ///  
        /// CodeDom provider that is to be used to generate the client code. 
        /// 
        ///  
        /// CLR namespace in which to generate the client code.
        /// 
        /// 
        /// The configuration into which we will put bindings/endpoints for this service 
        /// reference. May be Null/Nothing.
        ///  
        ///  
        /// The namespace that is to be used in configuration for this service reference.
        ///  
        /// 
        /// Service provider that we'll pass on to import extensions that accept our site:ing
        /// mechanism
        ///  
        /// 
        /// Type loader that can be used to find reference assemblies and/or resolve shared service and 
        /// data contract types. 
        /// 
        ///  
        /// The target framework version number. The higher 16 bits contains the major version number, and low 16 bits contains minor version number.
        /// 
        /// 
        /// Schema importer extension to be used for typed datasets. 
        /// 
        ///  
        /// A VSWCFServiceContractGenerator instance that contains the result of the generation. To get 
        /// hold of the generated information, you can query it's properties.
        ///  
        public static VSWCFServiceContractGenerator GenerateCodeAndConfiguration(SvcMapFile svcMapFile,
                                             System.Configuration.Configuration toolConfiguration,
                                             System.CodeDom.Compiler.CodeDomProvider codeDomProvider,
                                             string proxyNamespace, 
                                             System.Configuration.Configuration targetConfiguration,
                                             string configurationNamespace, 
                                             IServiceProvider serviceProviderForImportExtensions, 
                                             IContractGeneratorReferenceTypeLoader typeLoader,
                                             int targetFrameworkVersion, 
                                             System.Type typedDataSetSchemaImporterExtension)
        {
            if (svcMapFile == null) throw new ArgumentNullException("svcMapFile");
            if (codeDomProvider == null) throw new ArgumentNullException("codeDomProvider"); 
            if (typedDataSetSchemaImporterExtension == null) throw new ArgumentNullException("typedDataSetSchemaImporterExtension");
 
            List importErrors = new List(); 
            List proxyGenerationErrors = new List();
 
            CodeCompileUnit targetCompileUnit = new CodeCompileUnit();

            WsdlImporter wsdlImporter = CreateWsdlImporter(svcMapFile,
                                                           toolConfiguration, 
                                                           targetCompileUnit,
                                                           codeDomProvider, 
                                                           proxyNamespace, 
                                                           serviceProviderForImportExtensions,
                                                           typeLoader, 
                                                           targetFrameworkVersion,
                                                           importErrors,
                                                           typedDataSetSchemaImporterExtension);
 
            ServiceContractGenerator contractGenerator = CreateContractGenerator(svcMapFile.ClientOptions,
                                                                                wsdlImporter, 
                                                                                targetCompileUnit, 
                                                                                proxyNamespace,
                                                                                targetConfiguration, 
                                                                                typeLoader,
                                                                                targetFrameworkVersion,
                                                                                importErrors);
 
            try
            { 
                List serviceEndpointList = new List(); 
                IEnumerable bindingCollection;
                IEnumerable contractCollection; 

                ImportWCFModel(wsdlImporter,
                                 targetCompileUnit,
                                 importErrors, 
                                 out serviceEndpointList,
                                 out bindingCollection, 
                                 out contractCollection); 

                Dictionary serviceEndpointToChannelEndpointElementMap; 
                List proxyGeneratedContractTypes;

                GenerateProxy(wsdlImporter,
                              contractGenerator, 
                              targetCompileUnit,
                              proxyNamespace, 
                              configurationNamespace, 
                              contractCollection,
                              bindingCollection, 
                              serviceEndpointList,
                              proxyGenerationErrors,
                              out serviceEndpointToChannelEndpointElementMap,
                              out proxyGeneratedContractTypes); 

                if (IsVBCodeDomProvider(codeDomProvider)) 
                { 
                    PatchOutParametersInVB(targetCompileUnit);
                } 

                return new VSWCFServiceContractGenerator(importErrors,
                                                         targetCompileUnit,
                                                         targetConfiguration, 
                                                         bindingCollection,
                                                         contractCollection, 
                                                         serviceEndpointList, 
                                                         serviceEndpointToChannelEndpointElementMap,
                                                         proxyGeneratedContractTypes, 
                                                         proxyGenerationErrors);
            }
            catch (Exception ex)
            { 
                // fatal error... (workaround for bug #135242)
                // We want to convert fatal error exception to a normal code generator error message, 
                // so the user could find information from pervious errors to find KB topic. 
                proxyGenerationErrors.Add(new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode, 
                                    String.Empty,
                                    ex,
                                    false));
 
                return new VSWCFServiceContractGenerator(importErrors,
                                                        new CodeCompileUnit(), 
                                                        targetConfiguration, 
                                                        new List(),
                                                        new List(), 
                                                        new List(),
                                                        new Dictionary(),
                                                        new List(),
                                                        proxyGenerationErrors); 
            }
 
        } 

 
        /// 
        /// Instantiate and configure a ServiceContractGenerator to be used for code and config
        /// generation.
        ///  
        /// 
        /// Options set in the SvcMap file to control the code/config generation. 
        ///  
        /// 
        /// The WsdlImporter that is to be used to import the metadata for this service reference. 
        /// 
        /// 
        /// Compile unit into which we will generate the client code
        ///  
        /// 
        /// The CLR namespace into which we will generate the client code. 
        ///  
        /// 
        /// Optional configuration into which we will generate the endpoints/bindings corresponding 
        /// to this service reference. May be Null/Nothing, in which case we will not generate config.
        /// 
        /// 
        /// Type loader that can be used to find reference assemblies and/or resolve shared service and 
        /// data contract types.
        ///  
        ///  
        /// The target framework version number. The higher 16 bits contains the major version number, and low 16 bits contains minor version number.
        ///  
        /// 
        /// The list into which we will add any errors while importing the metadata.
        /// 
        ///  
        protected static ServiceContractGenerator CreateContractGenerator(ClientOptions proxyOptions,
                                            WsdlImporter wsdlImporter, 
                                            CodeCompileUnit targetCompileUnit, 
                                            string proxyNamespace,
                                            System.Configuration.Configuration targetConfiguration, 
                                            IContractGeneratorReferenceTypeLoader typeLoader,
                                            int targetFrameworkVersion,
                                            IList importErrors)
        { 
            ServiceContractGenerator contractGenerator = new ServiceContractGenerator(targetCompileUnit, targetConfiguration);
 
            // We want to generate all types into the proxy namespace CLR namespace. We indicate 
            // this by adding a namespace mapping from all XML namespaces ("*") to the namespace
            // the caller told us to generate the client code in. 
            contractGenerator.NamespaceMappings.Add("*", proxyNamespace);

            if (proxyOptions.GenerateInternalTypes)
            { 
                contractGenerator.Options |= ServiceContractGenerationOptions.InternalTypes;
            } 
            else 
            {
                contractGenerator.Options &= ~ServiceContractGenerationOptions.InternalTypes; 
            }

            if (proxyOptions.GenerateAsynchronousMethods)
            { 
                contractGenerator.Options |= ServiceContractGenerationOptions.AsynchronousMethods;
                if (targetFrameworkVersion >= FRAMEWORK_VERSION_35) 
                { 
                    contractGenerator.Options |= ServiceContractGenerationOptions.EventBasedAsynchronousMethods;
                } 
            }
            else
            {
                contractGenerator.Options &= ~ServiceContractGenerationOptions.AsynchronousMethods; 
            }
 
            if (proxyOptions.GenerateMessageContracts) 
            {
                contractGenerator.Options |= ServiceContractGenerationOptions.TypedMessages; 
            }
            else
            {
                contractGenerator.Options &= ~ServiceContractGenerationOptions.TypedMessages; 
            }
 
            // If we have a type loader, we tell the contract generator and wsdl importer about 
            // all shared types and assemblies that we've specified in the proxy options...
            if (typeLoader != null) 
            {
                foreach (ContractMapping mapping in proxyOptions.ServiceContractMappingList)
                {
                    try 
                    {
                        Type sharedType = typeLoader.LoadType(mapping.TypeName); 
 
                        // verify that the type is shareable - if not, we generate an error...
                        if (!IsTypeShareable(sharedType)) 
                        {
                            importErrors.Add(
                                    new ProxyGenerationError(
                                        ProxyGenerationError.GeneratorState.GenerateCode, 
                                        String.Empty,
                                        new FormatException(String.Format(CultureInfo.CurrentCulture, WCFModelStrings.ReferenceGroup_SharedTypeMustBePublic, mapping.TypeName))) 
                                ); 
                            continue;
                        } 

                        // Get a contract description corresponding to the type we wanted to share
                        ContractDescription contract = ContractDescription.GetContract(sharedType);
 
                        if (!String.Equals(mapping.Name, contract.Name, StringComparison.Ordinal) ||
                                !String.Equals(mapping.TargetNamespace, contract.Namespace, StringComparison.Ordinal)) 
                        { 
                            // mismatch
                            importErrors.Add( 
                                    new ProxyGenerationError(
                                        ProxyGenerationError.GeneratorState.GenerateCode,
                                        String.Empty,
                                        new FormatException(String.Format(CultureInfo.CurrentCulture, WCFModelStrings.ReferenceGroup_ServiceContractMappingMissMatch, mapping.TypeName, contract.Namespace, contract.Name, mapping.TargetNamespace, mapping.Name))) 
                                );
                        } 
 
                        XmlQualifiedName qname = new XmlQualifiedName(contract.Name, contract.Namespace);
                        wsdlImporter.KnownContracts.Add(qname, contract); 
                        contractGenerator.ReferencedTypes.Add(contract, sharedType);
                    }
                    catch (Exception ex)
                    { 
                        importErrors.Add(new ProxyGenerationError(
                                        ProxyGenerationError.GeneratorState.GenerateCode, 
                                        String.Empty, 
                                        ex));
                    } 
                }
            }

            foreach (NamespaceMapping namespaceMapping in proxyOptions.NamespaceMappingList) 
            {
                contractGenerator.NamespaceMappings.Add(namespaceMapping.TargetNamespace, namespaceMapping.ClrNamespace); 
            } 

            return contractGenerator; 
        }

        /// 
        /// Generate Proxy Code and (if available) configuration 
        /// 
        /// The contract generator to use 
        /// Compile unit into which we should generate the client code 
        /// CLR namespace into which we should generate the client code
        /// Namespace to use in configuration 
        /// The contracts for which we should generate code and optionally config
        /// The bindings we should generate config for
        /// The endpoints we should generate config for
        /// A list of errors encountered while generating the client 
        /// Map from service endpoint to the configuration element for the endpoint
        /// The generated contract types 
        protected static void GenerateProxy(WsdlImporter importer, 
                                            ServiceContractGenerator contractGenerator,
                                            CodeCompileUnit targetCompileUnit, 
                                            string proxyNamespace,
                                            string configurationNamespace,
                                            IEnumerable contractCollection,
                                            IEnumerable bindingCollection, 
                                            List serviceEndpointList,
                                            IList proxyGenerationErrors, 
                                            out Dictionary serviceEndpointToChannelEndpointElementMap, 
                                            out List proxyGeneratedContractTypes)
        { 
            // Parameter checking
            if (serviceEndpointList == null) throw new ArgumentNullException("serviceEndpointList");
            if (bindingCollection == null) throw new ArgumentNullException("bindingCollection");
            if (contractCollection == null) throw new ArgumentNullException("contractCollection"); 
            if (proxyGenerationErrors == null) throw new ArgumentNullException("proxyGenerationErrors");
 
            proxyGeneratedContractTypes = new List(); 
            serviceEndpointToChannelEndpointElementMap = new Dictionary();
 
            try
            {
                HttpBindingExtension httpBindingEx = importer.WsdlImportExtensions.Find();
 
                foreach (ContractDescription contract in contractCollection)
                { 
                    if (httpBindingEx == null || !httpBindingEx.IsHttpBindingContract(contract) || serviceEndpointList.Any(endpoint => endpoint.Contract == contract)) 
                    {
                        CodeTypeReference typeReference = contractGenerator.GenerateServiceContractType(contract); 
                        if (typeReference != null)
                        {
                            // keep the (targetNamespace, portType) -> CLR type map table...
 
                            string baseType = typeReference.BaseType;
 
                            GeneratedContractType generatedType = new GeneratedContractType(contract.Namespace, contract.Name, baseType, baseType); 
                            proxyGeneratedContractTypes.Add(generatedType);
                        } 
                    }
                }

                // We should only import the Binding & Endpoints if there is a configuration storage... 
                if (contractGenerator.Configuration != null)
                { 
                    foreach (ServiceEndpoint endpoint in serviceEndpointList) 
                    {
                        ChannelEndpointElement endpointElement = null; 
                        contractGenerator.GenerateServiceEndpoint(endpoint, out endpointElement);
                        serviceEndpointToChannelEndpointElementMap[endpoint] = endpointElement;
                    }
 
                    foreach (System.ServiceModel.Channels.Binding bindingDescription in bindingCollection)
                    { 
                        string bindingSectionName = null; 
                        string bindingConfigurationName = null;
                        // Generate binding will change the state of the contractGenerator... 
                        contractGenerator.GenerateBinding(bindingDescription, out bindingSectionName, out bindingConfigurationName);
                    }

                } 

                PatchConfigurationName(proxyNamespace, 
                                       configurationNamespace, 
                                       proxyGeneratedContractTypes,
                                       serviceEndpointToChannelEndpointElementMap.Values, 
                                       targetCompileUnit);
            }
            finally
            { 
                foreach (MetadataConversionError error in contractGenerator.Errors)
                { 
                    proxyGenerationErrors.Add(new ProxyGenerationError(error)); 
                }
            } 
        }

        /// 
        /// Create appropriate XmlSerializerImportOptions for the generator 
        /// 
        /// Options for the code/config generation 
        /// Compile unit we are going to generate the client code in 
        /// CodeDom provider for the language we are using
        /// CLR namespace we'll put the client code in 
        /// 
        protected static XmlSerializerImportOptions CreateXmlSerializerImportOptions(
                                ClientOptions proxyOptions,
                                CodeCompileUnit targetCompileUnit, 
                                System.CodeDom.Compiler.CodeDomProvider codeDomProvider,
                                string proxyNamespace, 
                                System.Type typedDataSetSchemaImporterExtension) 
        {
            System.ServiceModel.Channels.XmlSerializerImportOptions xmlSerializerOptions = new XmlSerializerImportOptions(targetCompileUnit); 
            System.Web.Services.Description.WebReferenceOptions webReferenceOptions = new System.Web.Services.Description.WebReferenceOptions();

            webReferenceOptions.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties | System.Xml.Serialization.CodeGenerationOptions.GenerateOrder;
 
            if (proxyOptions.EnableDataBinding)
            { 
                webReferenceOptions.CodeGenerationOptions |= System.Xml.Serialization.CodeGenerationOptions.EnableDataBinding; 
            }
 
            webReferenceOptions.SchemaImporterExtensions.Add(typedDataSetSchemaImporterExtension.AssemblyQualifiedName);
            webReferenceOptions.SchemaImporterExtensions.Add(typeof(System.Data.DataSetSchemaImporterExtension).AssemblyQualifiedName);

            /* 

 
 

 



 

 
 

 



*/ 

            xmlSerializerOptions.WebReferenceOptions = webReferenceOptions; 
            xmlSerializerOptions.CodeProvider = codeDomProvider; 

            xmlSerializerOptions.ClrNamespace = proxyNamespace; 

            return xmlSerializerOptions;
        }
 
        /// 
        /// Create an appropriate XsdDataContractImporter for the generator 
        ///  
        /// Code/config generation options to use
        /// CodeCompileUnit into which we will generate the client code 
        /// CodeDomProvider for the language we will use to generate the client
        /// CLR namespace in which the client code will be generated
        /// Service used to resolve type/assembly names (strings) to actual Types and Assemblies
        /// Targetted Framework version number 
        /// List of errors encountered. New errors will be added to this list
        ///  
        protected static XsdDataContractImporter CreateDataContractImporter( 
                ClientOptions proxyOptions,
                CodeCompileUnit targetCompileUnit, 
                System.CodeDom.Compiler.CodeDomProvider codeDomProvider,
                string proxyNamespace,
                IContractGeneratorReferenceTypeLoader typeLoader,
                int targetFrameworkVersion, 
                IList importErrors)
        { 
            System.Runtime.Serialization.XsdDataContractImporter xsdDataContractImporter = new System.Runtime.Serialization.XsdDataContractImporter(targetCompileUnit); 
            System.Runtime.Serialization.ImportOptions options = new System.Runtime.Serialization.ImportOptions();
 
            options.CodeProvider = codeDomProvider;

            // We specify that we want to generate all types from all XML namespaces into
            // our proxy namespace. By default, each XML namespace get's its own CLR namespace 
            options.Namespaces.Add("*", proxyNamespace);
            options.GenerateInternal = proxyOptions.GenerateInternalTypes; 
            options.GenerateSerializable = proxyOptions.GenerateSerializableTypes; 
            options.EnableDataBinding = proxyOptions.EnableDataBinding;
            options.ImportXmlType = proxyOptions.ImportXmlTypes; 

            if (typeLoader != null)
            {
                IEnumerable referencedTypes = LoadSharedDataContractTypes(proxyOptions, typeLoader, targetFrameworkVersion, importErrors); 
                if (referencedTypes != null)
                { 
                    foreach (Type sharedType in referencedTypes) 
                    {
                        options.ReferencedTypes.Add(sharedType); 
                    }
                }

                IEnumerable referencedCollectionTypes = LoadSharedCollectionTypes(proxyOptions, typeLoader, importErrors); 
                if (referencedCollectionTypes != null)
                { 
                    foreach (Type collectionType in referencedCollectionTypes) 
                    {
                        options.ReferencedCollectionTypes.Add(collectionType); 
                    }
                }

            } 

            foreach (NamespaceMapping namespaceMapping in proxyOptions.NamespaceMappingList) 
            { 
                options.Namespaces.Add(namespaceMapping.TargetNamespace, namespaceMapping.ClrNamespace);
            } 

            xsdDataContractImporter.Options = options;

            return xsdDataContractImporter; 
        }
 
        ///  
        /// Load DataContract types which could be used in the code generator (shared types)
        ///  
        /// Options controlling the generation
        /// Type loader to resolve referenced assemblies and types
        /// Targetted Framework version number
        /// Errors encountered while loading the shared data contracts 
        /// 
        /// A list of CLR types from referenced assemblies and/or specific types that we want to share 
        ///  
        /// 
        protected static IEnumerable LoadSharedDataContractTypes( 
                ClientOptions proxyOptions, IContractGeneratorReferenceTypeLoader typeLoader, int targetFrameworkVersion, IList importErrors)
        {
            if (typeLoader == null) throw new ArgumentNullException("typeLoader");
 
            // the value in sharedTypeTable is why we add this type in the shared type list.
            // if it is only added because it is in the referenced assembly, the value will be null, otherwise it contains the entry in the type inclusion list 
            // if the type is also in the exclusion list, we will report an error if the type is comming from the inclusion list, but no error if it comes from a referenced assembly only. 
            Dictionary sharedTypeTable = new Dictionary();
 
            // load all types in referencedAssemblies
            IEnumerable referencedAssemblies = LoadReferenedAssemblies(proxyOptions, typeLoader, importErrors);
            if (referencedAssemblies != null)
            { 
                foreach (Assembly referencedAssembly in referencedAssemblies)
                { 
                    try 
                    {
                        foreach (Type typeInAssembly in referencedAssembly.GetTypes()) 
                        {
                            if (IsTypeShareable(typeInAssembly))
                            {
                                sharedTypeTable.Add(typeInAssembly, null); 
                            }
                        } 
                    } 
                    catch (Exception ex)
                    { 
                        // fail to load one type in an assembly: warning message
                        importErrors.Add(
                                new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode, 
                                    String.Empty,
                                    ex, 
                                    true)); 
                    }
                } 
            }

            // load types in DataContractTypeList
            foreach (ReferencedType referencedType in proxyOptions.ReferencedDataContractTypeList) 
            {
                try 
                { 
                    Type sharedType = typeLoader.LoadType(referencedType.TypeName);
 
                    // verify...
                    if (!IsTypeShareable(sharedType))
                    {
                        importErrors.Add( 
                                new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode, 
                                    String.Empty, 
                                    new FormatException(String.Format(CultureInfo.CurrentCulture, WCFModelStrings.ReferenceGroup_SharedTypeMustBePublic, referencedType.TypeName)))
                            ); 
                        continue;
                    }

                    sharedTypeTable[sharedType] = referencedType; 
                }
                catch (Exception ex) 
                { 
                    importErrors.Add(new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode, 
                                    String.Empty,
                                    ex));
                }
            } 

            // remove excluded types 
            foreach (ReferencedType excludedType in proxyOptions.ExcludedTypeList) 
            {
                try 
                {
                    Type sharedType = typeLoader.LoadType(excludedType.TypeName);

                    if (sharedTypeTable.ContainsKey(sharedType)) 
                    {
                        if (sharedTypeTable[sharedType] != null) 
                        { 
                            // error message
                            importErrors.Add(new ProxyGenerationError( 
                                            ProxyGenerationError.GeneratorState.GenerateCode,
                                            String.Empty,
                                            new Exception(String.Format(CultureInfo.CurrentCulture, WCFModelStrings.ReferenceGroup_DataContractExcludedAndIncluded, excludedType.TypeName))));
                        } 
                        sharedTypeTable.Remove(sharedType);
                    } 
                } 
                catch (Exception ex)
                { 
                    // waring message for excludedTypes
                    importErrors.Add(new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode,
                                    String.Empty, 
                                    ex,
                                    true)); 
                } 
            }
 
            // remove unsupported types
            foreach (Type unsupportedType in GetUnsupportedTypes(targetFrameworkVersion))
            {
                sharedTypeTable.Remove(unsupportedType); 
            }
 
            return sharedTypeTable.Keys; 
        }
 
        /// 
        /// Get list of types which are not supported in the targetted framework.
        /// 
        /// Targetted Framework version number 
        /// 
        ///  
        private static IEnumerable GetUnsupportedTypes(int targetFrameworkVersion) 
        {
 
            if (targetFrameworkVersion < FRAMEWORK_VERSION_35)
            {
                // NOTE: do we need load those types with typeLoader?
                return unsupportedTypesInFramework30; 
            }
 
            return new Type[0]; 
        }
 
        /// 
        /// Ensure that the ConfigurationName attribute on service contracts and the channel endpoint elements all agree on the
        /// name of the service contract.
        /// We want to avoid having root/default namespace values persisted in config, since that would require us 
        /// to update config whenever the default/root namespace changes, so we make sure that we exclude it
        /// from the ConfigurationName attribute and the channel endpoint element we generate. 
        /// 
        /// For VB, the root namespace is not actually present in the generated code, so we typically don't have to
        /// do anything (the configuration and proxy namespaces are equal) but for C#, we need to strip out the 
        /// default namespace.
        /// 
        /// 
        /// CLR namespace into which we will generate the service in the CodeCompileUnit 
        /// 
        ///  
        /// The namespace that we expect to use in configuration. 
        /// 
        ///  
        /// The contracts that we have generated
        /// 
        /// 
        /// All channel endpoints we have generated 
        /// 
        ///  
        /// The compile unit into which we generated the client 
        /// 
        private static void PatchConfigurationName( 
                                    string proxyNamespace,
                                    string configNamespace,
                                    IEnumerable generatedContracts,
                                    IEnumerable endpoints, 
                                    CodeCompileUnit targetCompileUnit
            ) 
        { 

            // Since the name has to match between configuration and the name we put in the ConfigurationName 
            // attribute in code, we may have some patching to do - but only if the proxy namespace is not equal
            // to the configuration namespace...
            if (configNamespace != null && !configNamespace.Equals(proxyNamespace, StringComparison.Ordinal))
            { 
                string proxyNamespaceHead = MakePeriodTerminatedNamespacePrefix(proxyNamespace);
                string configNamespaceHead = MakePeriodTerminatedNamespacePrefix(configNamespace); 
 
                // We need to fix up the configuration name for all generated contracts...
                foreach (GeneratedContractType contract in generatedContracts) 
                {
                    contract.ConfigurationName = ReplaceNamespace(proxyNamespaceHead, configNamespaceHead, contract.ConfigurationName);
                }
 
                // ..and we need to fix up all elements in config...
                foreach (ChannelEndpointElement endpoint in endpoints) 
                { 
                    endpoint.Contract = ReplaceNamespace(proxyNamespaceHead, configNamespaceHead, endpoint.Contract);
                } 

                // ...and all ConfigurationName values in service contract attributes in the generated code as well...
                PatchConfigurationNameInServiceContractAttribute(targetCompileUnit, proxyNamespace, configNamespace);
            } 
        }
 
        ///  
        /// If the type name begins with the namespace specified in originalNamespace, replace the namespace
        /// for the given type name with the namespace specified in the replacementNamespace parameter. 
        /// 
        /// 
        /// Original namespace to look for.
        /// Must either be an empty string ("") or end with a period (".") 
        /// 
        ///  
        /// Namespace to replace original namespace with 
        /// Muse either be an empty string ("") or end with a period...
        ///  
        /// Typename on which to do the replacement
        /// 
        /// The new type name (potentially the same as passed in)
        ///  
        private static string ReplaceNamespace(string originalNamespace, string replacementNamespace, string typeName)
        { 
            Debug.Assert(originalNamespace.Length == 0 || originalNamespace.EndsWith(".", StringComparison.Ordinal)); 
            Debug.Assert(replacementNamespace.Length == 0 || replacementNamespace.EndsWith(".", StringComparison.Ordinal));
            Debug.Assert(typeName != null); 

            if (typeName.StartsWith(originalNamespace, StringComparison.Ordinal))
            {
                // Strip out the original namespace and replace it with the new namespace 
                return replacementNamespace + typeName.Substring(originalNamespace.Length);
            } 
            else 
            {
                return typeName; 
            }
        }

        ///  
        /// Given the namespace, return either an empty string (if the given namespace was NULL or emtpy)
        /// or a period-terminated (".") string. 
        ///  
        /// 
        ///  
        /// Either an empty string or a string that ends with a period (".")
        /// Can never return Null...
        /// 
        private static string MakePeriodTerminatedNamespacePrefix(string ns) 
        {
            if (String.IsNullOrEmpty(ns)) 
            { 
                return "";
            } 
            else if (!ns.EndsWith(".", StringComparison.Ordinal))
            {
                return ns + ".";
            } 
            else
            { 
                return ns; 
            }
        } 

        /// 
        /// Determine if a type can be shared.
        /// 
        /// In order for a type to be shareable for service references, it has to be a
        /// public type... 
        ///  
        /// 
        ///  
        private static bool IsTypeShareable(Type t)
        {
            if (t == null)
            { 
                System.Diagnostics.Debug.Fail("Why are you asking if a NULL type is shareable?");
                return false; 
            } 

            return t.IsPublic || t.IsNestedPublic; 
        }

        /// 
        /// Load referenced assemblies 
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        private static IEnumerable LoadReferenedAssemblies(ClientOptions proxyOptions, IContractGeneratorReferenceTypeLoader typeLoader, IList importErrors)
        {
            List referencedAssemblies = new List(); 
            if (proxyOptions.ReferenceAllAssemblies)
            { 
                try 
                {
                    IEnumerable loadingErrors = null; 
                    IEnumerable allAssemblies = null;
                    typeLoader.LoadAllAssemblies(out allAssemblies, out loadingErrors);
                    if (loadingErrors != null)
                    { 
                        // treat as warning messages
                        foreach (Exception ex in loadingErrors) 
                        { 
                            importErrors.Add(new ProxyGenerationError(
                                            ProxyGenerationError.GeneratorState.GenerateCode, 
                                            String.Empty,
                                            ex,
                                            true));
                        } 
                    }
 
                    if (allAssemblies != null) 
                    {
                        referencedAssemblies.AddRange(allAssemblies); 
                    }
                }
                catch (Exception ex)
                { 
                    importErrors.Add(new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode, 
                                    String.Empty, 
                                    ex));
                } 
            }

            foreach (ReferencedAssembly referencedAssembly in proxyOptions.ReferencedAssemblyList)
            { 
                try
                { 
                    Assembly refAssembly = typeLoader.LoadAssembly(referencedAssembly.AssemblyName); 
                    if (refAssembly != null && !referencedAssemblies.Contains(refAssembly))
                    { 
                        referencedAssemblies.Add(refAssembly);
                    }
                }
                catch (Exception ex) 
                {
                    importErrors.Add(new ProxyGenerationError( 
                                    ProxyGenerationError.GeneratorState.GenerateCode, 
                                    String.Empty,
                                    ex)); 
                }
            }
            return referencedAssemblies;
        } 

        ///  
        /// Load the list of types that we have specified as collection types in our client options. 
        /// The collection types will be used to generate collections in the data contracts.
        ///  
        /// Options specifying the list of collection types
        /// Type loader that resolves type names to actual CLR types
        /// Errors encountered while loading the collection types
        ///  
        /// 
        protected static IEnumerable LoadSharedCollectionTypes(ClientOptions proxyOptions, IContractGeneratorReferenceTypeLoader typeLoader, IList importErrors) 
        { 
            List referencedCollectionTypes = new List();
            foreach (ReferencedCollectionType referencedCollectionMapping in proxyOptions.CollectionMappingList) 
            {
                try
                {
                    Type collectionType = typeLoader.LoadType(referencedCollectionMapping.TypeName); 

                    // verify... 
                    if (!IsTypeShareable(collectionType)) 
                    {
                        importErrors.Add( 
                                new ProxyGenerationError(
                                    ProxyGenerationError.GeneratorState.GenerateCode,
                                    String.Empty,
                                    new FormatException(String.Format(CultureInfo.CurrentCulture, WCFModelStrings.ReferenceGroup_SharedTypeMustBePublic, referencedCollectionMapping.TypeName))) 
                            );
                        continue; 
                    } 

                    referencedCollectionTypes.Add(collectionType); 
                }
                catch (Exception ex)
                {
                    importErrors.Add(new ProxyGenerationError( 
                                    ProxyGenerationError.GeneratorState.GenerateCode,
                                    String.Empty, 
                                    ex)); 
                }
            } 
            return referencedCollectionTypes;
        }

        ///  
        /// Create an appropriate WsdlImporter for the generator
        ///  
        ///  
        /// 
        ///  
        /// 
        /// 
        /// 
        /// Targetted Framework version number 
        /// 
        ///  
        ///  
        protected static WsdlImporter CreateWsdlImporter(SvcMapFile svcMapFile,
                                                      System.Configuration.Configuration toolConfiguration, 
                                                      CodeCompileUnit targetCompileUnit,
                                                      System.CodeDom.Compiler.CodeDomProvider codeDomProvider,
                                                      string targetNamespace,
                                                      IServiceProvider serviceProviderForImportExtensions, 
                                                      IContractGeneratorReferenceTypeLoader typeLoader,
                                                      int targetFrameworkVersion, 
                                                      IList importErrors, 
                                                      System.Type typedDataSetSchemaImporterExtension)
        { 
            List metadataSections = CollectMetadataDocuments(svcMapFile.MetadataList, importErrors);

            WsdlImporter importer = null;
 
            ClientOptions.ProxySerializerType serializerType = svcMapFile.ClientOptions.Serializer;
            if (serializerType == ClientOptions.ProxySerializerType.Auto && ContainsHttpBindings(metadataSections)) 
            { 
                // NOTE: HTTP Get/Post binding indicates an old web service. We use XmlSerializer to prevent generating dup classes.
                // Please check devdiv bug 94078 
                serializerType = ClientOptions.ProxySerializerType.XmlSerializer;
            }

            if (toolConfiguration != null) 
            {
                ServiceModelSectionGroup serviceModelSection = ServiceModelSectionGroup.GetSectionGroup(toolConfiguration); 
 
                if (serviceModelSection != null)
                { 
                    Collection wsdlImportExtensions = serviceModelSection.Client.Metadata.LoadWsdlImportExtensions();
                    Collection policyImportExtensions = serviceModelSection.Client.Metadata.LoadPolicyImportExtensions();

                    // If we have specified a specific serializer to use, we remove 
                    // the other serializer...
                    switch (serializerType) 
                    { 
                        case ClientOptions.ProxySerializerType.DataContractSerializer:
                            RemoveExtension(typeof(XmlSerializerMessageContractImporter), wsdlImportExtensions); 
                            break;
                        case ClientOptions.ProxySerializerType.XmlSerializer:
                            RemoveExtension(typeof(DataContractSerializerMessageContractImporter), wsdlImportExtensions);
                            break; 
                        case ClientOptions.ProxySerializerType.Auto:
                            break; 
                        default: 
                            System.Diagnostics.Debug.Fail("Unknown serializer");
                            break; 
                    }

                    ProvideImportExtensionsWithContextInformation(svcMapFile, serviceProviderForImportExtensions, wsdlImportExtensions, policyImportExtensions);
 
                    wsdlImportExtensions.Add(new HttpBindingExtension());
 
                    // Create Importer... 
                    importer = new WsdlImporter(new MetadataSet(metadataSections), policyImportExtensions, wsdlImportExtensions);
                } 
            }

            if (importer == null)
            { 
                importer = new WsdlImporter(new MetadataSet(metadataSections));
            } 
 
            // DevDiv 124333 - Always add DataContract importer (even if we are in XmlSerializerMode) to
            // enable importing Fault contracts... 
            importer.State.Add(typeof(System.Runtime.Serialization.XsdDataContractImporter),
                           CreateDataContractImporter(svcMapFile.ClientOptions, targetCompileUnit, codeDomProvider, targetNamespace, typeLoader, targetFrameworkVersion, importErrors));

            if (serializerType != ClientOptions.ProxySerializerType.DataContractSerializer) 
            {
                importer.State.Add(typeof(System.ServiceModel.Channels.XmlSerializerImportOptions), 
                               CreateXmlSerializerImportOptions(svcMapFile.ClientOptions, 
                                                                targetCompileUnit,
                                                                codeDomProvider, 
                                                                targetNamespace,
                                                                typedDataSetSchemaImporterExtension));
            }
 
            // Read the UseSerializerForFaults from Reference.svcmap, create a FaultImportOptions using this information
 	        // and pass it to WSDL Importer. 
            FaultImportOptions faultOptions = new FaultImportOptions(); 
            faultOptions.UseMessageFormat = svcMapFile.ClientOptions.UseSerializerForFaults;
            importer.State.Add(typeof(System.ServiceModel.FaultImportOptions), faultOptions); 

            // Read the WrappedOptions from Reference.svcmap, create a WrappedOptions using this information
            // and pass it to WSDL Importer.
            WrappedOptions wrappedOptions = new WrappedOptions(); 
            wrappedOptions.WrappedFlag = svcMapFile.ClientOptions.Wrapped;
            importer.State.Add(typeof(System.ServiceModel.Channels.WrappedOptions), wrappedOptions); 
 
            return importer;
        } 

        /// 
        /// Look through all the import extensions to see if any of them want access to
        ///   the service reference's extension files.  They tell us this by implementing 
        ///   the interface IWcfReferenceReceiveContextInformation.
        ///  
        ///  
        /// 
        ///  
        /// 
        internal static void ProvideImportExtensionsWithContextInformation(SvcMapFile svcMapFile, IServiceProvider serviceProviderForImportExtensions, IEnumerable wsdlImportExtensions, IEnumerable policyImportExtensions)
        {
            // Only make this copy if we need to (not the mainline case) 
            Dictionary extensionFileContents = null;
 
            foreach (IWsdlImportExtension wsdlImportExtension in wsdlImportExtensions) 
            {
                System.Web.Compilation.IWcfReferenceReceiveContextInformation receiveContext = 
                    wsdlImportExtension as System.Web.Compilation.IWcfReferenceReceiveContextInformation;
                if (receiveContext != null)
                {
                    if (extensionFileContents == null) 
                    {
                        extensionFileContents = CreateDictionaryOfCopiedExtensionFiles(svcMapFile); 
                    } 
                    receiveContext.ReceiveImportContextInformation(
                        extensionFileContents, 
                        serviceProviderForImportExtensions);
                }
            }
            foreach (IPolicyImportExtension policyImportExtension in policyImportExtensions) 
            {
                System.Web.Compilation.IWcfReferenceReceiveContextInformation receiveContext = 
                    policyImportExtension as System.Web.Compilation.IWcfReferenceReceiveContextInformation; 
                if (receiveContext != null)
                { 
                    if (extensionFileContents == null)
                    {
                        extensionFileContents = CreateDictionaryOfCopiedExtensionFiles(svcMapFile);
                    } 
                    receiveContext.ReceiveImportContextInformation(
                        extensionFileContents, 
                        serviceProviderForImportExtensions); 
                }
            } 
        }

        /// 
        /// Remove specific wsdl importer extension 
        /// 
        ///  
        /// The extension to remove 
        /// 
        ///  
        /// The collection to remove the extension from
        /// 
        /// 
        ///  
        private static void RemoveExtension(Type extensionType, Collection wsdlImportExtensions)
        { 
            Debug.Assert(wsdlImportExtensions != null); 

            for (int i = 0; i < wsdlImportExtensions.Count; i++) 
            {
                if (wsdlImportExtensions[i].GetType() == extensionType)
                    wsdlImportExtensions.RemoveAt(i);
            } 
        }
 
        ///  
        /// Creates a dictionary containing a copy of the contents of all of the extension files
        ///  
        /// 
        private static Dictionary CreateDictionaryOfCopiedExtensionFiles(SvcMapFile svcMapFile)
        {
            Dictionary extensionFileContents = new Dictionary(); 
            foreach (ExtensionFile extensionFile in svcMapFile.Extensions)
            { 
                // If the extension file was not successfully loaded, do not include it in the 
                //   collection.  Users are more likely to expect that the extension file won't
                //   be in the collection on an error than they are to assume they have to check 
                //   if the byte array we return is null or not.
                if (extensionFile.ContentBuffer != null && extensionFile.IsBufferValid)
                {
                    extensionFileContents.Add(extensionFile.Name, (byte[])extensionFile.ContentBuffer.Clone()); 
                }
            } 
 
            return extensionFileContents;
        } 


        /// 
        /// Merge metadata files to prepare code generation 
        /// 
        /// metadata collection 
        ///  
        protected static List CollectMetadataDocuments(IEnumerable metadataList, IList importErrors)
        { 
            List metadataCollection = new List();

            foreach (MetadataFile metadataItem in metadataList)
            { 
                if (!metadataItem.Ignore)
                { 
                    try 
                    {
                        MetadataSection metadataSection = metadataItem.CreateMetadataSection(); 
                        if (metadataSection != null)
                        {
                            metadataCollection.Add(metadataSection);
                        } 
                    }
                    catch (Exception ex) 
                    { 
                        importErrors.Add(ConvertMetadataErrorToProxyGenerationError(metadataItem, ex));
                    } 
                }
            }

            RemoveDuplicatedSchemaItems(metadataCollection, importErrors); 
            CheckDuplicatedWsdlItems(metadataCollection, importErrors);
 
            return metadataCollection; 
        }
 
        /// 
        /// Convert metadata loading errors into proxy generation error messages
        /// 
        ///  
        /// 
        internal static ProxyGenerationError ConvertMetadataErrorToProxyGenerationError(MetadataFile metadataItem, Exception ex) 
        { 
            ProxyGenerationError generationError = null;
            if (ex is XmlSchemaException) 
            {
                generationError = new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata, metadataItem.FileName, (XmlSchemaException)ex);
            }
            else if (ex is XmlException) 
            {
                generationError = new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata, metadataItem.FileName, (XmlException)ex); 
            } 
            else if (ex is InvalidOperationException)
            { 
                System.Xml.Schema.XmlSchemaException schemaException = ex.InnerException as System.Xml.Schema.XmlSchemaException;
                if (schemaException != null)
                {
                    generationError = new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata, metadataItem.FileName, schemaException); 
                }
                else 
                { 
                    System.Xml.XmlException xmlException = ex.InnerException as System.Xml.XmlException;
                    if (xmlException != null) 
                    {
                        generationError = new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata, metadataItem.FileName, xmlException);
                    }
                    else 
                    {
                        generationError = new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata, metadataItem.FileName, (InvalidOperationException)ex); 
                    } 
                }
            } 
            else
            {
                generationError = new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata, metadataItem.FileName, ex);
            } 
            return generationError;
        } 
 
        /// 
        /// Remove duplicated schema items from the metadata collection 
        /// 
        /// 
        private static void RemoveDuplicatedSchemaItems(List metadataCollection, IList importErrors)
        { 
            Dictionary schemaList = new Dictionary();
 
            // add independent schema files... 
            foreach (MetadataSection metadataSection in metadataCollection)
            { 
                if (metadataSection.Dialect == MetadataSection.XmlSchemaDialect)
                {
                    XmlSchema schema = (XmlSchema)metadataSection.Metadata;
                    schemaList.Add(schema, metadataSection); 
                }
            } 
 
            // add embedded files...
            foreach (MetadataSection metadataSection in metadataCollection) 
            {
                if (metadataSection.Dialect == MetadataSection.ServiceDescriptionDialect)
                {
                    System.Web.Services.Description.ServiceDescription wsdl = (System.Web.Services.Description.ServiceDescription)metadataSection.Metadata; 
                    foreach (XmlSchema schema in wsdl.Types.Schemas)
                    { 
                        schema.SourceUri = wsdl.RetrievalUrl; 
                        schemaList.Add(schema, metadataSection);
                    } 
                }
            }

            IEnumerable duplicatedSchemas; 
            SchemaMerger.MergeSchemas(schemaList.Keys, importErrors, out duplicatedSchemas);
 
            if (duplicatedSchemas != null) 
            {
                foreach (XmlSchema schema in duplicatedSchemas) 
                {
                    Debug.Assert(schemaList.ContainsKey(schema), "The schema list should not contain any of the schemas returned in the duplicateSchemas...");

                    MetadataSection metadataSection = schemaList[schema]; 
                    if (metadataSection.Dialect == MetadataSection.XmlSchemaDialect)
                    { 
                        metadataCollection.Remove(metadataSection); 
                    }
                    else if (metadataSection.Dialect == MetadataSection.ServiceDescriptionDialect) 
                    {
                        System.Web.Services.Description.ServiceDescription wsdl = (System.Web.Services.Description.ServiceDescription)metadataSection.Metadata;
                        wsdl.Types.Schemas.Remove(schema);
                    } 
                }
            } 
        } 

        ///  
        /// check all wsdl files, and generate error messages if one contract have multiple different specifications
        /// 
        /// 
        private static void CheckDuplicatedWsdlItems(IList metadataCollection, IList importErrors) 
        {
            List wsdlFiles = new List(); 
            foreach (MetadataSection metadataSection in metadataCollection) 
            {
                if (metadataSection.Dialect == MetadataSection.ServiceDescriptionDialect) 
                {
                    System.Web.Services.Description.ServiceDescription wsdl = (System.Web.Services.Description.ServiceDescription)metadataSection.Metadata;
                    wsdlFiles.Add(wsdl);
                } 
            }
 
            WsdlInspector.CheckDuplicatedWsdlItems(wsdlFiles, importErrors); 
        }
 
        /// 
        /// Given a WSDL importer, a set of metadata files and a compile unit, import the metadata
        /// files.
        ///  
        /// 
        ///  
        ///  
        /// Errors encountered whie importing the model. Any new errors will be appended to this list.
        ///  
        /// List of endpoints imported
        /// The collection of bindings imported
        /// The collection of contracts imported
        protected static void ImportWCFModel(WsdlImporter importer, 
                                          System.CodeDom.CodeCompileUnit compileUnit,
                                          IList generationErrors, 
                                          out List serviceEndpointList, 
                                          out IEnumerable bindingCollection,
                                          out IEnumerable contractCollection) 
        {
            // We want to remove soap1.2 endpoints for ASMX references, but we can't use the "normal" way
            // of using a IWsdlImportExtension to do so since BeforeImport is called too late (DevDiv 7857)
            // If DevDiv 7857 is fixed, we can remove the following two lines and instead add the 
            // AsmxEndpointPickerExtension to the importer's wsdl import extensions...
            IWsdlImportExtension asmxFixerUpper = new AsmxEndpointPickerExtension(); 
            asmxFixerUpper.BeforeImport(importer.WsdlDocuments, null, null); 

            // NOTE: we should import Endpoint before Contracts, otherwise some information (related to binding) will be lost in the model (devdiv: 22396) 
            serviceEndpointList = new List();

            //
            // First we import all the endpoints (ports). This is required so that any WsdlImportExtension's BeforeImport 
            // gets called before we actually try to import anything from the WSDL object model.
            // If we don't do this, we run into problems if any wsdl import extensions want to delete a specific port 
            // and this port happens to be the first port we try to import (you can't interrupt the import) 
            importer.ImportAllEndpoints();
 
            //
            // We need to go through each endpoint element and "re-import" it in order to get the mapping
            // between the wsdlPort and the ServiceEndpoint... Importing the same endpoint twice is a no-op
            // as far as the endpoint collection is concerned - it is simply a hashtable lookup to retreive 
            // the already generated information...
            // 
            foreach (System.Web.Services.Description.ServiceDescription wsdlServiceDescription in importer.WsdlDocuments) 
            {
                foreach (System.Web.Services.Description.Service wsdlService in wsdlServiceDescription.Services) 
                {
                    foreach (System.Web.Services.Description.Port servicePort in wsdlService.Ports)
                    {
                        try 
                        {
                            ServiceEndpoint newEndpoint = importer.ImportEndpoint(servicePort); 
                            serviceEndpointList.Add(newEndpoint); 
                        }
                        catch (InvalidOperationException) 
                        {
                            // Invalid operation exceptions should already be in the errors collection for the importer, so we don't
                            // need to add another generationError. The most probable cause for this is that the we failed to import
                            // the endpoint... 
                        }
                        catch (Exception ex) 
                        { // It is bad, because WsdlImporter.WsdlImportException is a private class 
                            generationErrors.Add(new ProxyGenerationError(ProxyGenerationError.GeneratorState.GenerateCode, wsdlServiceDescription.RetrievalUrl, ex));
                        } 
                    }
                }
            }
 

            bindingCollection = importer.ImportAllBindings(); 
            System.Diagnostics.Debug.Assert(bindingCollection != null, "The importer should never return a NULL binding collection!"); 

            contractCollection = importer.ImportAllContracts(); 
            System.Diagnostics.Debug.Assert(contractCollection != null, "The importer should never return a NULL contract collection!");

            foreach (MetadataConversionError error in importer.Errors)
            { 
                generationErrors.Add(new ProxyGenerationError(error));
            } 
        } 

 

        /// 
        /// This function patches ServiceContractAttribute in the generated proxy code. It replaces all proxyNamespace in the attribute
        ///   to configNamespace.  The configNamespace does not depend on defaultNamespace of the project. 
        /// 
        ///  
        ///  
        /// 
        ///  
        private static void PatchConfigurationNameInServiceContractAttribute(CodeCompileUnit proxyCodeUnit, string proxyNamespace, string configNamespace)
        {
            if (proxyNamespace == null)
            { 
                proxyNamespace = String.Empty;
            } 
 
            string proxyNamespaceHead = MakePeriodTerminatedNamespacePrefix(proxyNamespace);
            string configNamespaceHead = MakePeriodTerminatedNamespacePrefix(configNamespace); 

            if (proxyCodeUnit != null)
            {
                foreach (CodeNamespace proxyCodeNamespace in proxyCodeUnit.Namespaces) 
                {
                    // Find the namespace we are patching... 
                    if (String.Equals(proxyNamespace, proxyCodeNamespace.Name, StringComparison.Ordinal)) 
                    {
                        // ...and all types in each namespace... 
                        foreach (CodeTypeDeclaration typeDeclaration in proxyCodeNamespace.Types)
                        {
                            if (typeDeclaration.IsInterface)
                            { 
                                // ...and each attribute on each interface...
                                foreach (CodeAttributeDeclaration codeAttribute in typeDeclaration.CustomAttributes) 
                                { 
                                    // find System.ServiceModel.ServiceContractAttribute attribute.
                                    if (String.Equals(codeAttribute.AttributeType.BaseType, typeof(System.ServiceModel.ServiceContractAttribute).FullName, StringComparison.Ordinal)) 
                                    {
                                        foreach (CodeAttributeArgument argument in codeAttribute.Arguments)
                                        {
                                            if (String.Equals(argument.Name, "ConfigurationName", StringComparison.Ordinal)) 
                                            {
                                                // we only fix the string here 
                                                CodePrimitiveExpression valueExpression = argument.Value as CodePrimitiveExpression; 
                                                if (valueExpression != null && valueExpression.Value is string)
                                                { 
                                                    valueExpression.Value = ReplaceNamespace(proxyNamespaceHead, configNamespaceHead, (string)valueExpression.Value);
                                                }
                                            }
                                        } 
                                    }
                                } 
                            } 
                        }
                    } 
                }
            }
        }
 

        ///  
        /// Patch VB code for output parameters. 
        ///
        /// Visual Basic doesn't support Out parameters - they are all generated as ByRef. 
        /// Unfortunately, the CodeDom provider doesn't add an Out attribute to the ByRef
        /// parameters, so we have to do that ourselves...
        /// 
        ///  
        /// 
        private static void PatchOutParametersInVB(CodeCompileUnit codeCompileUnit) 
        { 
            foreach (CodeNamespace codeNamespace in codeCompileUnit.Namespaces)
            { 
                foreach (CodeTypeDeclaration codeClass in codeNamespace.Types)
                {
                    PatchTypeDeclaration(codeClass);
                } 
            }
        } 
 
        /// 
        /// Patch TypeDeclaration in VB code for output parameters 
        /// 
        /// 
        /// 
        private static void PatchTypeDeclaration(CodeTypeDeclaration codeClass) 
        {
            foreach (CodeTypeMember member in codeClass.Members) 
            { 
                if (member is CodeTypeDeclaration)
                { 
                    // Recurse down in nested types...
                    PatchTypeDeclaration((CodeTypeDeclaration)member);
                }
                else if (member is CodeMemberMethod) 
                {
                    CodeMemberMethod method = member as CodeMemberMethod; 
                    foreach (CodeParameterDeclarationExpression parameter in method.Parameters) 
                    {
                        if (parameter.Direction == FieldDirection.Out) 
                        {
                            // Make sure that all Out parameters have an  attribute
                            //
                            // First check for explicit  declaration to avoid adding duplicate attributes. 
                            if (!IsDefinedInCodeAttributeCollection(typeof(System.Runtime.InteropServices.OutAttribute), parameter.CustomAttributes))
                            { 
                                parameter.CustomAttributes.Add(OutAttribute); 
                            }
                        } 
                    }
                }
            }
        } 

        ///  
        /// check whether code attribuate has already been declared. 
        /// 
        ///  
        /// 
        /// 
        /// 
        private static bool IsDefinedInCodeAttributeCollection(Type type, CodeAttributeDeclarationCollection metadata) 
        {
            foreach (CodeAttributeDeclaration attribute in metadata) 
            { 
                if (String.Equals(attribute.Name, type.FullName, StringComparison.Ordinal) || String.Equals(attribute.Name, type.Name, StringComparison.Ordinal))
                { 
                    return true;
                }
            }
            return false; 
        }
 
        ///  
        /// Check whether it is VB language
        ///  
        /// 
        /// 
        /// 
        private static bool IsVBCodeDomProvider(System.CodeDom.Compiler.CodeDomProvider codeDomProvider) 
        {
            string fileExtension = codeDomProvider.FileExtension; 
            try 
            {
                string language = System.CodeDom.Compiler.CodeDomProvider.GetLanguageFromExtension(fileExtension); 
                return String.Equals(language, VB_LANGUAGE_NAME, StringComparison.OrdinalIgnoreCase);
            }
            catch (System.Configuration.ConfigurationException)
            { 
                // not defined extension
                return false; 
            } 
        }
 
        /// 
        /// check whether HTTP Binding is used in those metadata files
        /// 
        /// metadata files 
        /// 
        ///  
        private static bool ContainsHttpBindings(IEnumerable metadataCollection) 
        {
            foreach (MetadataSection metadataSection in metadataCollection) 
            {
                if (metadataSection.Dialect == MetadataSection.ServiceDescriptionDialect)
                {
                    System.Web.Services.Description.ServiceDescription wsdlFile = (System.Web.Services.Description.ServiceDescription)metadataSection.Metadata; 
                    if (ContainsHttpBindings(wsdlFile))
                    { 
                        return true; 
                    }
                } 
            }
            return false;
        }
 
        /// 
        /// check whether HTTP Binding is used in one wsdl file 
        ///  
        /// one wsdl
        ///  
        /// 
        internal static bool ContainsHttpBindings(System.Web.Services.Description.ServiceDescription wsdlFile)
        {
            foreach (System.Web.Services.Description.Binding binding in wsdlFile.Bindings) 
            {
                foreach (object extension in binding.Extensions) 
                { 
                    System.Web.Services.Description.HttpBinding httpBinding = extension as System.Web.Services.Description.HttpBinding;
                    if (httpBinding != null) 
                    {
                        return true;
                    }
                } 
            }
            return false; 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK