Udostępnij za pośrednictwem


Enumerating Binding Element Extensions

As a follow up to my previous posts “Is there an easy way to enumerate the bindings listed in configuration?” and “Enumerating Behavior Extensions”, this week I discuss how to enumerate the last WCF configuration extension points: binding elements.

Before I go further into this discussion, I need to define a few terms.

· Binding element – An element that defines a specific entry in the binding stack. Binding elements examples include encodings, transports, security, etc.

· Runtime binding element – The binding element object used by the WCF runtime as part of the binding stack. When binding element appears without “runtime” specified this references the configuration object responsible for exposing the runtime binding element to the WCF configuration system.

· Custom binding – A binding constructed in configuration by explicitly adding the specific binding elements desired and configuring those elements directly.

· Configured custom binding – An entry in the custom binding configuration collection (i.e. <customBinding>) that correlates to a named set of binding element extensions and their configuration.

· “Available to my app” – Exists in the configuration merged view created when opening the application.config file associated with “my app”.

Now, without further ado, the discussion begins.

Similar to enumerating behaviors listed in configuration, when I get asked about binding elements people really do want to enumerate these extensions. The only point of clarification lies around whether they want all extension elements available to an application, or just those used in a specific configuration. For the purpose of this posting, I will explore the following four scenarios:

1. Enumerate all of the binding element extensions available to my app

2. Enumerate all of the binding elements in a configured custom binding

Enumerate all of the binding element extensions available to my app

The specific scenario I hear most for this question involves creating a dynamically configurable service / client making use of custom bindings. Essentially, the enumeration will fill some type of editor control for setting the binding elements on a custom binding used by an endpoint (think wizard type application here). The solution I describe for this scenario actually accomplishes two things. First, it discovers all of the binding element configuration element names available to an application. Second, it examines each of the binding elements found and discovers the underlying runtime binding element associated with that configuration element.

The solution becomes straight forward when you, once again, understand that all of the WCF configuration extensions (including those built into the WCF product) are registered in one of three collections under the Extensions configuration section in the System.ServiceModel configuration section group. For this post I will focus on the BindingElementExtensions collection. These extension collections contain a number of add elements that include a name and type property. The name property corresponds to the xml element name that references this binding. The type property corresponds to the type that knows how to deserialized the configuration XML for this binding.

 

<configuration>

  <system.serviceModel>

    <extensions>

      <bindingElementExtensions>

        <add name="httpTransport" type="System.ServiceModel.Configuration.HttpTransportElement, System.ServiceModel, ..."/>

      </bindingElementExtensions>

    </extensions>

  </system.serviceModel>

</configuration>

 

The first part of this solution simply involves enumerating the entries in the BindingElementExtensions collection and capturing each entries' name.

The second part of this solution involves enumerating the entries in the extension collection and capturing each entries’ type. Since this type will implement the BindingElementExtensionElement base class, the solution can create an instance of the binding element extension type and cast it to BindingElementExtensionElement. To facilitate enumerations like this, BindingElementExtensionElement contains a helper property (get only), BindingElementType, which returns the type of the underlying runtime binding element configured by this extension, which satisfies the second part of this solution.

Here is a quick bit of code that accomplishes this task and displays the information to the console:

static void EnumerateAllAvailableBindingElementExtensions()

{

    ExtensionsSection serviceModelExtensions = (ExtensionsSection)ConfigurationManager.GetSection("system.serviceModel/extensions");

    if (97 > Console.WindowWidth)

    {

  Console.WindowWidth = 97;

    }

    Console.WriteLine("{0,-22} : {1}",

        "Xml Element Name",

        "Underlying Binding Element Type");

    foreach (ExtensionElement bindingElementExtension in serviceModelExtensions.BindingElementExtensions)

  {

        BindingElementExtensionElement bindingElement = (BindingElementExtensionElement)Activator.CreateInstance(Type.GetType(bindingElementExtension.Type));

        Console.WriteLine("{0,-22} : {1}",

            bindingElementExtension.Name,

       bindingElement.BindingElementType.FullName);

    }

}

 

Enumerate all of the binding elements in a configured custom binding

Like the previous scenario, this specific scenario often involves some sort of dynamically configurable application (again think wizard). An important distinction to make for this solution revolves around its completeness. This solution only discovers binding elements contained in the configured custom bindings and ignores binding elements that do not exist in any configured custom binding instances.

<configuration>

  <system.serviceModel>

    <bindings>

      <customBinding>

        <binding name="myCustomBinding">

        <httpTransport/>

        </binding>

      </customBinding>

    </bindings>

  </system.serviceModel>

</configuration>

 

This solution also starts with enumerating through each of the configured custom bindings. A CustomBindingElement can be seen as a collection of BindingElementExtensionElements, thus I enumerate through each extension included in a given custom binding. To help identify WCF configuration extension objects where consumed, the abstract base class for all WCF extension elements (ServiceModelExtensionElement) contains the helper property (get only) ConfigurationElementName. This returns the XML element name corresponding to a particular extensions element, and tracks back to that extension’s name attribute in the ‘extensions’ section registration. When enumerating configured binding elements for this scenario, my solution makes use of this property to list each binding element extension’s element name as well as the underlying runtime binding element type.

Here is a quick bit of code that accomplishes this task and displays the information to the console:

static void EnumerateConfiguredCustomBindings()

{

    BindingsSection bindings = (BindingsSection)ConfigurationManager.GetSection("system.serviceModel/bindings");

    if (97 > Console.WindowWidth)

    {

        Console.WindowWidth = 97;

    }

    foreach (CustomBindingElement customBinding in bindings.CustomBinding.Bindings)

    {

        Console.WriteLine("Binding '{0}':", customBinding.Name);

        foreach (BindingElementExtensionElement bindingElement in customBinding)

        {

            Console.WriteLine("{0,-22} : {1}",

                bindingElement.ConfigurationElementName,

                bindingElement.BindingElementType.FullName);

        }

    }

}

 

I hope this sheds some light on the various methods of enumerating binding elements available to an application using the WCF configuration system.

Mark Gabarra

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm

Comments