Click here to Skip to main content
15,886,518 members
Articles / Desktop Programming / Win32

Routing Manager for WCF4

Rate me:
Please Sign up or sign in to vote.
5.00/5 (38 votes)
29 Apr 2010CPOL18 min read 108K   2.5K   92  
This article describes a design, implementation and usage of the Custom Routing Manager for managing messages via Routing Service built-in .Net 4 Technology.
//*****************************************************************************
//    Description.....ESB Core
//                                
//    Author..........Roman Kiss, rkiss@pathcom.com
//    Copyright © 2005 ATZ Consulting Inc.     
//                        
//    Date Created:    07/07/07
//
//    Date        Modified By     Description
//-----------------------------------------------------------------------------
//    03/03/09    Roman Kiss     Initial Revision
//    04/04/10    Roman Kiss     Modifying for .Net4 (routing service)
//
//*****************************************************************************
//  

#region Namespaces
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Xml;
using System.ServiceModel.Routing;
using System.ServiceModel.Routing.Configuration;
using System.Linq;
using System.Xml.Linq;
#endregion

namespace RKiss.ConfigLib
{
    #region ConfigHelper
    public class ConfigHelper
    {
        private ConfigHelper()
        {
        }

        /// <summary>
        /// Deserialize xml to the instance for a specific configuration section type
        /// </summary>
        /// <typeparam name="T">type of the section</typeparam>
        /// <param name="config">xml representat of the configuration section</param>
        /// <returns>Type of the configuration section</returns>
        public static T DeserializeSection<T>(string config) where T : class
        {
            T cfgSection = Activator.CreateInstance<T>();
            byte[] buffer = new ASCIIEncoding().GetBytes(config.TrimStart(new char[] { '\r', '\n', ' ' }));
            XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
            xmlReaderSettings.ConformanceLevel = ConformanceLevel.Fragment;

            using (MemoryStream ms = new MemoryStream(buffer))
            {
                using (XmlReader reader = XmlReader.Create(ms, xmlReaderSettings))
                {
                    try
                    {
                        EsbTrace.Event(TraceEventType.Verbose, 0, "Deserialize section '{0}' from stream", new object[] { typeof(T).FullName});

                        Type cfgType = typeof(ConfigurationSection);
                        MethodInfo mi = cfgType.GetMethod("DeserializeSection", BindingFlags.Instance | BindingFlags.NonPublic);
                        mi.Invoke(cfgSection, new object[] { reader });
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(string.Format("DeserializeSection<{0}> failed, {1}", cfgSection.ToString(), ex.InnerException == null ? ex.Message : ex.InnerException.Message));
                    }
                }
            }
            return cfgSection;
        }

        public static KeyValueConfigurationCollection AppSettings(string config)
        {
            KeyValueConfigurationCollection col = new KeyValueConfigurationCollection();
            if (string.IsNullOrEmpty(config) == false)
            {
                AppSettingsSection appSettings = null;
                if (config.TrimStart().StartsWith("<"))
                {
                    EsbTrace.Event(TraceEventType.Verbose, 0, "Deserialize section AppSettings from stream");
                    appSettings = ConfigHelper.DeserializeSection<AppSettingsSectionHelper>(config).AppSettings;
                }
                else
                {
                    ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
                    filemap.ExeConfigFilename = config;
                    Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
                    if (configuration != null)
                    {
                        EsbTrace.Event(TraceEventType.Verbose, 0, "Deserialize section AppSettings from configFile", new object[] { config });
                        appSettings = configuration.AppSettings;                       
                    }
                }
                if (appSettings != null && appSettings.Settings.Count > 0)
                {
                    return appSettings.Settings;
                }
            }
            return col;
        }

        public static XElement GetSection(XElement config, string sectionName)
        {
            return GetSection(config, sectionName, true);
        }
        public static XElement GetSection(XElement config, string sectionName, bool bThrow)
        {
            if (config == null)
                throw new ArgumentNullException("config");
            if (string.IsNullOrEmpty(sectionName))
                throw new ArgumentNullException("sectionName");

            if (config == null || config.Element("system.serviceModel") == null || config.Element("system.serviceModel").Element("services") == null)
                throw new Exception("Failed for validation of the <system.serviceModel> and <services> sections in the config resource");

            XElement element = config.Element("system.serviceModel").Element(sectionName);
            if (element == null && bThrow)
                throw new Exception(string.Format(@"Missing 'system.serviceModel\{0}' section in the config resource", sectionName));

            return element;
        }

        public static XElement GetService(XElement config, string name)
        {
            return GetService(config, name, true);
        }
        public static XElement GetService(XElement config, string name, bool bThrow)
        {
            if (config == null)
                throw new ArgumentNullException("config");
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            var services = GetSection(config, "services");
            var service = services.Descendants("service").FirstOrDefault(e => e.Attribute("name").Value == name);
            if (service == null && bThrow)
                throw new Exception(string.Format("There is no 'service @name={0}' in the config resource", name));

            return service;
        }

        public static XElement GetServiceBehavior(XElement config, string behaviorName, bool bThrow)
        {
            if (config == null)
                throw new ArgumentNullException("config");
            if (string.IsNullOrEmpty(behaviorName))
                throw new ArgumentNullException("behaviorName");

            var query = ConfigHelper.GetSection(config, "behaviors").Element("serviceBehaviors");
            if (query == null && bThrow)
                throw new Exception(@"There is no 'behaviors\serviceBehaviors' section in the config resource");

            var behavior = query.Descendants("behavior").FirstOrDefault(e => e.Attribute("name").Value == behaviorName);
            if (behavior == null && bThrow)
                throw new Exception(string.Format(@"Doesn't exist a 'system.serviceModel\behaviors\serviceBehaviors\behavior @name={0}' section in the config resource.", behaviorName));

            return behavior;
        }
    }
    #endregion

    #region AppSettingsSectionHelper
    public sealed class AppSettingsSectionHelper : ConfigurationSection
    {
        private AppSettingsSection _appSettings = new AppSettingsSection();
        public AppSettingsSection AppSettings { get { return _appSettings; } }

        protected override void DeserializeSection(XmlReader reader)
        {
            Type cfgType = typeof(ConfigurationSection);
            MethodInfo mi = cfgType.GetMethod("DeserializeElement", BindingFlags.Instance | BindingFlags.NonPublic);

            reader.ReadStartElement("configuration");
            reader.ReadToFollowing("appSettings");
            reader.MoveToContent();
            mi.Invoke(_appSettings, new object[] { reader, false });
            reader.ReadEndElement();
            reader.ReadEndElement();
        }
    }
    #endregion

    #region ServiceModelConfigHelper
    public class ServiceModelConfigHelper
    {
        private ServiceModelConfigHelper()
        {
        }

        public static ServiceModelSection GetServiceModel(string configFilename)
        {
            ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
            filemap.ExeConfigFilename = string.IsNullOrEmpty(configFilename) ? AppDomain.CurrentDomain.SetupInformation.ConfigurationFile : Path.GetFullPath(configFilename);
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
            ServiceModelSectionGroup sm = ServiceModelSectionGroup.GetSectionGroup(config);
            return new ServiceModelSection { Behaviors = sm.Behaviors, Bindings = sm.Bindings, Client = sm.Client, Diagnostics = sm.Diagnostic, Services = sm.Services, Extensions = sm.Extensions };
        }

        /// <summary>
        /// Get a specific ServiceElement from the config file
        /// </summary>
        /// <param name="name"></param>
        /// <param name="configFilename"></param>
        /// <returns></returns>
        /// <remarks>The default (process) config file is used when argument configFilename is empty/null.</remarks>
        public static ServiceElement GetServiceElement(string configurationName, string configFilename)
        {
            ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
            filemap.ExeConfigFilename = string.IsNullOrEmpty(configFilename) ? AppDomain.CurrentDomain.SetupInformation.ConfigurationFile : Path.GetFullPath(configFilename);
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
            ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);

            foreach (ServiceElement se in serviceModel.Services.Services)
            {
                if (se.Name == configurationName)
                {
                    return se;
                }
            }
            throw new ArgumentException(string.Format("The service '{0}' doesn't exist in the config {1}", configurationName, filemap.ExeConfigFilename));
        }

        public static ServiceElement GetServiceElement(string configurationName, Stream config)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// add service behaviors based on the config metadata
        /// </summary>
        /// <param name="host"></param>
        /// <param name="model"></param>
        public static void AddServiceBehaviors(ServiceHostBase host, ServiceModelSection model, string serviceConfigurationName)
        {
            //string serviceConfigurationName = host.Description.ConfigurationName;

            string behaviorConfigurationName = model.Services.Services[serviceConfigurationName].BehaviorConfiguration;
            if (!string.IsNullOrEmpty(behaviorConfigurationName))
            {
                MethodInfo mi = typeof(BehaviorExtensionElement).GetMethod("CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic);

                if (model.Behaviors.ServiceBehaviors.ContainsKey(behaviorConfigurationName) == false)
                    throw new Exception(string.Format("Missing service behavior '{0}' for service '{1}'", behaviorConfigurationName, serviceConfigurationName));

                //ServiceBehaviorElement sss = model.Behaviors.ServiceBehaviors.Cast<ServiceBehaviorElement>().FirstOrDefault(e => e.Name == behaviorConfigurationName);

                foreach (ServiceBehaviorElement sbe in model.Behaviors.ServiceBehaviors)
                {
                    if (sbe.Name == behaviorConfigurationName)
                    {
                        foreach (BehaviorExtensionElement bee in sbe)
                        {
                            IServiceBehavior behavior = mi.Invoke(bee, null) as IServiceBehavior;
                            host.Description.Behaviors.Add(behavior);
                            EsbTrace.Event(TraceEventType.Verbose, 0, "Add service behavior '{0}' to the host description", new object[] { bee.ConfigurationElementName});
                        }
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// add service's endpoint behaviors based on the config metadata
        /// </summary>
        /// <param name="host"></param>
        /// <param name="model"></param>
        public static void AddEndpointBehaviors(ServiceHostBase host, ServiceModelSection model, string serviceConfigurationName)
        {
            //string serviceConfigurationName = host.Description.ConfigurationName;

            MethodInfo mi = typeof(BehaviorExtensionElement).GetMethod("CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic);

            // walk through all endpoints for this service
            foreach (ServiceEndpointElement see in model.Services.Services[serviceConfigurationName].Endpoints)
            {
                if (string.IsNullOrEmpty(see.BehaviorConfiguration)) continue;

                if (model.Behaviors.EndpointBehaviors.ContainsKey(see.BehaviorConfiguration) == false)
                    throw new Exception(string.Format("Missing endpoint behavior '{0}' for service '{1}'", see.BehaviorConfiguration, serviceConfigurationName));

                foreach (EndpointBehaviorElement ebe in model.Behaviors.EndpointBehaviors)
                {
                    if (ebe.Name == see.BehaviorConfiguration)
                    {
                        foreach (string key in ebe.ElementInformation.Properties.Keys)
                        {
                            if (key == "name") continue;
                            IEndpointBehavior behavior = mi.Invoke(ebe.ElementInformation.Properties[key].Value, null) as IEndpointBehavior;
                            host.Description.Endpoints.Find(see.Address).Behaviors.Add(behavior);
                            EsbTrace.Event(TraceEventType.Verbose, 0, "Add endpoint behavior '{0}' to the host description", new object[] { key });
                        }
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// add binding for all service endpoints based on the config metadata
        /// </summary>
        /// <param name="host"></param>
        /// <param name="model"></param>
        public static void AddServiceEndpointBinding(ServiceHostBase host, ServiceModelSection model, string serviceConfigurationName)
        {
            //string serviceConfigurationName = host.Description.ConfigurationName;

            ServiceEndpointElementCollection endpoints = model.Services.Services[serviceConfigurationName].Endpoints;
            for (int ii = 0; ii < endpoints.Count; ii++)
            {
                if (host.Description.Endpoints[ii].Binding == null)
                {
                    string bindingConfigurationName = endpoints[ii].BindingConfiguration;
                    Binding binding = CreateEndpointBinding(null, bindingConfigurationName, model);
                    if (binding == null)
                        throw new Exception(string.Format("Missing endpoint binding '{0}' in the service '{1}'", bindingConfigurationName, serviceConfigurationName));
                    host.Description.Endpoints[ii].Binding = binding;
                    EsbTrace.Event(TraceEventType.Verbose, 0, "Add service endpoint binding '{0}' to the host description", new object[] { bindingConfigurationName });
                }
            }
        }

        /// <summary>
        /// Add client's endpoint behaviors
        /// </summary>
        /// <param name="behaviorConfiguration"></param>
        /// <param name="endpoint"></param>
        /// <param name="model"></param>
        public static void AddChannelEndpointBehaviors(string behaviorConfiguration, ServiceEndpoint endpoint, ServiceModelSection model)
        {
            if (endpoint == null)
                throw new ArgumentNullException("endpoint");

            if (string.IsNullOrEmpty(behaviorConfiguration))
                return;

            if (model.Behaviors.EndpointBehaviors.ContainsKey(behaviorConfiguration) == false)
                throw new Exception(string.Format("Missing endpoint behavior '{0}' for endpoint name '{1}'", behaviorConfiguration, endpoint.Name));

            MethodInfo mi = typeof(BehaviorExtensionElement).GetMethod("CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (EndpointBehaviorElement ebe in model.Behaviors.EndpointBehaviors)
            {
                if (ebe.Name == behaviorConfiguration)
                {
                    foreach (string key in ebe.ElementInformation.Properties.Keys)
                    {
                        if (key == "name") continue;
                        IEndpointBehavior behavior = mi.Invoke(ebe.ElementInformation.Properties[key].Value, null) as IEndpointBehavior;
                        endpoint.Behaviors.Add(behavior);
                        EsbTrace.Event(TraceEventType.Verbose, 0, "Add channel endpoint behavior '{0}' to the endpoint '{1}'", new object[] { key, behaviorConfiguration});
                    }
                    break;
                }
            }
        }

        /// <summary>
        /// create endpoint binding
        /// </summary>
        /// <param name="bindingConfigurationName"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public static Binding CreateEndpointBinding(string bindingName, string bindingConfigurationName, ServiceModelSection model)
        {
            Binding binding = null;

            #region standard default binding
            if (string.IsNullOrEmpty(bindingConfigurationName) && !string.IsNullOrEmpty(bindingName))
            {
                if ( bindingName == "netNamedPipeBinding")
                    binding = new NetNamedPipeBinding();
                else if (bindingName == "netTcpBinding")
                    binding = new NetTcpBinding();
                else if (bindingName == "netTcpContextBinding")
                    binding = new NetTcpContextBinding();
                else if (bindingName == "netPeerTcpBinding")
                    binding = new NetPeerTcpBinding();
                else if (bindingName == "netMsmqBinding")
                    binding = new NetMsmqBinding();
                else if (bindingName == "wsSHttpBinding")
                    binding = new WSHttpBinding();
                else if (bindingName == "wsHttpContextBinding")
                    binding = new WSHttpContextBinding();
                else if (bindingName == "basicHttpBinding")
                    binding = new BasicHttpBinding();
                else if (bindingName == "basicHttpContextBinding")
                    binding = new BasicHttpContextBinding();
                else if (bindingName == "webHttpBinding")
                    binding = new WebHttpBinding();
                else if (bindingName == "wsDualHttpBinding")
                    binding = new WSDualHttpBinding();
                else if (bindingName == "wsFederationHttpBinding")
                    binding = new WSFederationHttpBinding();
                else if (bindingName == "ws2007FederationHttpBinding")
                    binding = new WS2007FederationHttpBinding();
                else if (bindingName == "ws2007HttpBinding")
                    binding = new WS2007HttpBinding();
                return binding;
            }
            #endregion

            BindingCollectionElement bce = model.Bindings.BindingCollections.Find(delegate(BindingCollectionElement element)
            {
                if (element.ConfiguredBindings.Count == 0) return false;
                for (int ii = 0; ii < element.ConfiguredBindings.Count; ii++)
                {
                    if (element.ConfiguredBindings[ii].Name == bindingConfigurationName) 
                        return true;
                }
                return false;
            });

            if (bce == null)
            {
                EsbTrace.Event(TraceEventType.Warning, 0, "Can't find binding '{0}' in the collection", new object[] { bindingConfigurationName });
                return binding;
            }

            foreach (IBindingConfigurationElement configuredBinding in bce.ConfiguredBindings)
            {
                if (configuredBinding.Name != bindingConfigurationName) continue;

                if (bce.BindingType == typeof(CustomBinding))
                {
                    MethodInfo mi = typeof(BindingElementExtensionElement).GetMethod("CreateBindingElement", BindingFlags.Instance | BindingFlags.NonPublic);
                    foreach (CustomBindingElement cbe in model.Bindings.CustomBinding.Bindings)
                    {
                        if (bindingConfigurationName == cbe.Name)
                        {
                            CustomBinding cb = new CustomBinding();
                            foreach (BindingElementExtensionElement element in cbe)
                            {
                                cb.Elements.Add((BindingElement)mi.Invoke(element, null));
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Custom binding '{0}' has been created", new object[] { element.ConfigurationElementName });
                            }
                            return cb;
                        }
                    }
                    break;
                }
                else if (bce.BindingType == typeof(NetNamedPipeBinding))
                    binding = new NetNamedPipeBinding();
                else if (bce.BindingType == typeof(NetTcpBinding))
                    binding = new NetTcpBinding();
                else if (bce.BindingType == typeof(NetTcpContextBinding))
                    binding = new NetTcpContextBinding();
                else if (bce.BindingType == typeof(NetPeerTcpBinding))
                    binding = new NetPeerTcpBinding();
                else if (bce.BindingType == typeof(NetMsmqBinding))
                    binding = new NetMsmqBinding();
                else if (bce.BindingType == typeof(WSHttpBinding))
                    binding = new WSHttpBinding();
                else if (bce.BindingType == typeof(WSHttpContextBinding))
                    binding = new WSHttpContextBinding();
                else if (bce.BindingType == typeof(BasicHttpBinding))
                    binding = new BasicHttpBinding();
                else if (bce.BindingType == typeof(BasicHttpContextBinding))
                    binding = new BasicHttpContextBinding();
                else if (bce.BindingType == typeof(WebHttpBinding))
                    binding = new WebHttpBinding();
                else if (bce.BindingType == typeof(WSDualHttpBinding))
                    binding = new WSDualHttpBinding();
                else if (bce.BindingType == typeof(WSFederationHttpBinding))
                    binding = new WSFederationHttpBinding();
                else if (bce.BindingType == typeof(WS2007FederationHttpBinding))
                    binding = new WS2007FederationHttpBinding();
                else if (bce.BindingType == typeof(WS2007HttpBinding))
                    binding = new WS2007HttpBinding();
                else
                {
                    EsbTrace.Event(TraceEventType.Warning, 0, "Can't create binding for '{0}'", new object[] { bindingConfigurationName });
                    break;
                }

                configuredBinding.ApplyConfiguration(binding);
                EsbTrace.Event(TraceEventType.Verbose, 0, "The binding '{0}' has been created", new object[] { binding.Name });
                break;
            }
            return binding;
        }

        /// <summary>
        /// Create list of all client's endpoints
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static List<ServiceEndpoint> ListOfClientEndpoints(ServiceModelSection model)
        {
            List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>();
            if (model.Client != null && model.Client.Endpoints != null && model.Client.Endpoints.Count > 0)
            {
                foreach (ChannelEndpointElement element in model.Client.Endpoints)
                {
                    ServiceEndpoint endpoint = GetClientEndpoint(model, element.Name);
                    if (endpoint != null)
                        endpoints.Add(endpoint);
                }
            }
            return endpoints;
        }

        public static ServiceEndpoint GetClientEndpoint(ServiceModelSection model, string endpointName)
        {

            ServiceEndpoint endpoint = null;

            ChannelEndpointElement element = model.Client.Endpoints.Cast<ChannelEndpointElement>().FirstOrDefault(e=>e.Name == endpointName);
            if (element == null)
                throw new InvalidOperationException(string.Format("The client Endpoint '{0}' not found", endpointName));

            // find a contract type
            if (element.Contract != "*")
            {
                Type contractType = Type.GetType(element.Contract, false);
                if (contractType == null)
                {
                    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        contractType = assembly.GetType(element.Contract, false);
                        if (contractType != null)
                            break;
                    }
                }
                if (contractType == null) return endpoint;
                endpoint = new ServiceEndpoint(ContractDescription.GetContract(contractType));
            }
            else
            {
                endpoint = new ServiceEndpoint(new ContractDescription("contract")) { Contract = { ConfigurationName = "*" } };
            }

            endpoint.Address = new EndpointAddress(element.Address);
            endpoint.Name = element.Name;
            if (endpoint.Binding == null)
            {
                endpoint.Binding = CreateEndpointBinding(element.Binding, element.BindingConfiguration, model);
                if (endpoint.Binding == null)
                    throw new Exception(string.Format("Missing endpoint binding '{0}' in the endpoint name '{1}'", element.BindingConfiguration, element.Name));
            }
            ServiceModelConfigHelper.AddChannelEndpointBehaviors(element.BehaviorConfiguration, endpoint, model);

            return endpoint;
        }

        public static MessageFilterTable<IEnumerable<ServiceEndpoint>> CreateFilterTable(string config, string tableName)
        {
            if (string.IsNullOrEmpty(config))
                throw new ArgumentNullException("config");

            var model = ConfigHelper.DeserializeSection<ServiceModelSection>(config);
            if (model == null || model.Routing == null || model.Client == null)
                throw new Exception("Failed for validation of the <system.serviceModel> sections for routing service in the config resource");

            return CreateFilterTable(model, tableName);
        }
        
        public static MessageFilterTable<IEnumerable<ServiceEndpoint>> CreateFilterTable(ServiceModelSection model, string tableName)
        {
            MessageFilterTable<IEnumerable<ServiceEndpoint>> table = new MessageFilterTable<IEnumerable<ServiceEndpoint>>();

            FilterTableEntryCollection entries = model.Routing.FilterTables[tableName];
            if (entries == null)
                throw new Exception(string.Format("The table '{0}' doesn't exist.", tableName));

            List<ServiceEndpoint> clientEndpoints = ServiceModelConfigHelper.ListOfClientEndpoints(model);

            XmlNamespaceManager xmlNamespaces = new XPathMessageContext();
            foreach (NamespaceElement element in model.Routing.NamespaceTable)
            {
                xmlNamespaces.AddNamespace(element.Prefix, element.Namespace);
            }

            FilterElementCollection filters = model.Routing.Filters;
            foreach (FilterTableEntryElement entry in entries)
            {
                FilterElement filterElement = filters[entry.FilterName];
                if (filterElement == null)
                {
                    throw new InvalidOperationException(string.Format("Filter '{0}' not found", entry.FilterName));
                }
                MessageFilter filter = (MessageFilter)filterElement.GetType().InvokeMember("CreateFilter", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, filterElement, new object[] { xmlNamespaces, filters });
       
                IList<ServiceEndpoint> data = new List<ServiceEndpoint>();
                if (!string.IsNullOrEmpty(entry.BackupList))
                {
                    BackupEndpointCollection endpoints = model.Routing.BackupLists[entry.BackupList];
                    if (endpoints == null)
                       throw new InvalidOperationException(string.Format("BackupList '{0}' not found", entry.BackupList));
                    foreach (BackupEndpointElement endpointElement in endpoints)
                    {
                        var backupEndpoint = clientEndpoints.FirstOrDefault(e => e.Name == endpointElement.EndpointName);
                        if (backupEndpoint == null)
                            throw new InvalidOperationException(string.Format("backup Endpoint '{0}' not found", endpointElement.EndpointName));
                        data.Add(backupEndpoint);
                    }
                }

                var endpoint = clientEndpoints.FirstOrDefault(e => e.Name == entry.EndpointName);
                if(endpoint == null)
                    throw new InvalidOperationException(string.Format("Client Endpoint '{0}' not found", entry.EndpointName));

                data.Insert(0, endpoint);
                table.Add(filter, data, entry.Priority);
            }
            return table;
        }    
    }
    #endregion

    #region ServiceModelSection
    public sealed class ServiceModelSection : ConfigurationSection
    {
        public ServicesSection Services { get; set; }
        public ClientSection Client { get; set; }
        public BehaviorsSection Behaviors { get; set; }
        public BindingsSection Bindings { get; set; }
        public ExtensionsSection Extensions { get; set; }
        public DiagnosticSection Diagnostics { get; set; }
        public RoutingSection Routing { get; set; }

        protected override void DeserializeSection(XmlReader reader)
        {
            Type cfgType = typeof(ConfigurationSection);
            MethodInfo mi = cfgType.GetMethod("DeserializeElement", BindingFlags.Instance | BindingFlags.NonPublic);

            reader.ReadStartElement("configuration");
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                if (reader.Name == "system.serviceModel")
                {
                    reader.ReadStartElement();
                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        #region sections
                        string element = reader.Name;
                        try
                        {
                            if (reader.IsEmptyElement || reader.NodeType == XmlNodeType.Whitespace)
                            {
                                reader.Skip();
                                continue;
                            }

                            if (reader.Name == "diagnostics")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.diagnostics");  
                                Diagnostics = new DiagnosticSection();
                                mi.Invoke(Diagnostics, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else if (reader.Name == "extensions")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.extensions");  
                                Extensions = new ExtensionsSection();
                                mi.Invoke(Extensions, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else if (reader.Name == "services")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.services");  
                                Services = new ServicesSection();
                                mi.Invoke(Services, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else if (reader.Name == "bindings")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.bindings");  
                                Bindings = new BindingsSection();                  
                                mi.Invoke(Bindings, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else if (reader.Name == "behaviors")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.behaviors"); 
                                Behaviors = new BehaviorsSection();
                                mi.Invoke(Behaviors, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else if (reader.Name == "client")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.client"); 
                                Client = new ClientSection();
                                mi.Invoke(Client, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else if (reader.Name == "routing")
                            {
                                EsbTrace.Event(TraceEventType.Verbose, 0, "Deserializing system.serviceModel.routing");
                                this.Routing = new RoutingSection();
                                mi.Invoke(this.Routing, new object[] { reader, false });
                                reader.ReadEndElement();
                            }
                            else
                            {
                                reader.Skip();
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(string.Format("Deserializing '{0}' failed, {1}", element, ex.InnerException == null ? ex.Message : ex.InnerException.Message));
                        }
                        #endregion
                        reader.MoveToContent();
                    }
                }
                reader.Skip();
                reader.MoveToContent();
            }
            reader.ReadEndElement();
        }
    }
    #endregion


  

}









/////
//if (Extensions != null && Extensions.BindingElementExtensions != null && Extensions.BindingElementExtensions.Count > 0)
//{
//    PropertyInfo fi = typeof(BindingsSection).GetProperty("Properties", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic );
//    ConfigurationPropertyCollection properties = (ConfigurationPropertyCollection)fi.GetValue(Bindings, null);
//    if (properties != null)
//    {
//        foreach (ExtensionElement extensions in Extensions.BindingElementExtensions)
//        {
//            if (extensions != null)
//            {
//                ConfigurationProperty property = new ConfigurationProperty(extensions.Name, Type.GetType(extensions.Type, true), null, ConfigurationPropertyOptions.None);
//                properties.Add(property);
//            }
//        }
//    }
//}
/////

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions