For the last couple of days I have been stairing at the inner workings of WSE 2.0 (using that well known tool) and I must say it's a fine piece of craftmanship. My focus has been on the Microsoft.Web.Services2.Messaging namespace, which provides the infrastructure (at long last) to host a soap server in your own application (without reverting to ASP.NET runtime hosting). It takes a while to wrap your head around the workflow because I've never seen that many asynchronous methods used together. It is a good example of how to use delegates, asynccallbacks, waithandles, ... to provide a scalable messaging solution.
WaitHandleAsyncResult (found in Microsoft.Web.Services2) was a new concept to me. Basically an IAsyncResult implementation that doesn't fire an AsyncCallback until a WaitHandle is signalled. Very powerfull for multi-threaded communication and it's public(better rebuild it yourself in case they pull it from WSE 3.0). Too bad these kind of patterns don't get more attention. Another nice example (although hidden from the public eye) is Microsoft.Web.Services2.Messaging.SoapClient+SoapClientAsyncResult which shows you how to asynchronously send a soap request and on send completion, sit around and wait for the response to get back (again, asynchronously).
When building your own transport, beware to derive your custom Soap<transport>InputChannel from SoapInputChannel, unless you plan to rewrite SoapTransport.DispatchMessage. An interface-based contract would have done the trick here, but I must agree that it probably would have confused the custom transport developer. SoapInputChannel internally uses a System.Collections.Queue to buffer messages and SoapTransport.DispatchMessage puts them into the buffer. Also note that you can't configure your custom transport (and thus scheme) using the configuration file. You must do this in code (or write your own config section handler which does the lifting). For some reason, the folks implementing the SoapTcpTransport where not happy using the Begin/EndAccept members of a socket, and implemented a windows socket event sink. They must have had their reason for doing this ... wonder what it could be.
All in all a nice release ... one we can learn from.
UPDATE: Steve Main shows us how to configure your custom transport (scheme) using the configuration file [Permalink]
UPDATE II: After doing some more digging (actually stairing at same code over and over again) I finally found what I had been misinterpreting. If you specify a type attribute on the <messaging><transports><add> tag, another branch of the code is executed which does the transport type loading.
So to conclude,
<messaging>
<transports>
<add scheme="[Out-of-the-box transport scheme]"/>
</transports>
</messaging>
or
<messaging>
<transports>
<add scheme="[Custom transport scheme]" type="[Custom transport type]"/>
</transports>
</messaging>