Now that our Factories and Channels our built, we need to expose them to the Service/Proxy system. Channels fit into this system through the concept of a Binding. A binding represents the communication stack associated with a service endpoint.
In essense, a Binding is a top-level container for a collection of BindingElements. Each binding element is used to configure (and then build) a layer of the Channel stack. These binding elements are the core of how you configure and build a channel (both transport and layered).
Note that while the Channel interfaces are all free-threaded objects, the BindingElement configuration object is single-threaded.
UdpTransportBindingElement, which derives from BindingElement and IChannelBuilder, is the binding element for our Udp Factories. It overrides 2 methods in order to build the factories associated with our binding:
If we wanted to expose any other configuration knobs (such as a certain number of retries for added reliability), then these would be exposed as properties on UdpBindingElement and the information would be propagated to UdpChannelFactory and/or UdpListenerFactory at build time.
Bindings fall into two main categories:
Custom Binding usage
The first way our UdpBindingElement can be used is through a Custom Binding. A custom binding allows the user to create their own binding based on an arbitrary set of binding elements. By simply writing a BindingElement for your layer of the channel stack, any developer can now write a custom binding with Udp as its transport.
Custom bindings provide a large amout of flexibility, which is both a blessing and a curse. It’s very easy to shoot yourself in the foot by misconfiguring a custom binding. Usually only certain settings on a transport are compatible with certain settings on Security, Reliable Messaging, Transactions, etc. The way to address this miasma of combinatorics is through predefined bindings (also known as “standard” bindings).
Predefined Binding usage
Indigo provides a number of Predefined Bindings, such as BasicProfileBinding, NetProfileTcpBinding, and WsProfileBinding. Each of these bindings is associated with a well-defined class of services. For example, BasicProfileBinding is for use with ASMX-style services, WsProfileBinding is for WS-* enabled services such as BEA or Websphere, and NetProfileTcpBinding is for Indigo-based TCP services. Each of these predefined bindings is built on top of the same binding elements a custom binding would use, but they provide a simpler programming model that will yield channel stacks conformant with their target usage.
For our Udp experiment, we will create a “sample profile”, which allows for UDP and optional reliability (which will add Composite Duplex and Reliable Messaging to the Channel stack). SampleProfileUdpBinding, which derives from Binding, contains up to three binding elements within it: UdpTransportBindingElement, CompositeDuplexBindingElement, and ReliableSessionBindingElement. It exposes a few high-level knobs, and configures the resulting binding stack in CreateBindingElements():
> bindingElements = new
One more step remains now, and that is to expose our custom transport to the configuration system. Stay tuned 🙂