using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Text;
namespace System.ServiceModel.Dispatcher{
internal class BaseRequestProcessor
{
HandlersChain initialize_handlers_chain = new HandlersChain();
HandlersChain process_handlers_chain = new HandlersChain ();
HandlersChain error_handlers_chain = new HandlersChain ();
HandlersChain finalize_handlers_chain = new HandlersChain ();
protected BaseRequestProcessor () { }
protected virtual void ProcessRequest (MessageProcessingContext mrc)
{
initialize_handlers_chain.ProcessRequestChain (mrc);
using (new OperationContextScope (mrc.OperationContext)) {
try {
process_handlers_chain.ProcessRequestChain (mrc);
}
catch (Exception e) {
// FIXME: this is not really expected use of ChannelDispatcher.ErrorHandlers.
// They are now correctly used in process_handler_chain (namely OperationInvokerHandler).
// For this kind of "outsider" exceptions are actually left thrown
// (and could even cause server loop crash in .NET).
Console.WriteLine ("Exception " + e.Message + " " + e.StackTrace);
mrc.ProcessingException = e;
error_handlers_chain.ProcessRequestChain (mrc);
}
finally {
finalize_handlers_chain.ProcessRequestChain (mrc);
}
}
}
public HandlersChain InitializeChain
{
get { return initialize_handlers_chain; }
}
public HandlersChain ProcessingChain
{
get { return process_handlers_chain; }
}
public HandlersChain ErrorChain
{
get { return error_handlers_chain; }
}
public HandlersChain FinalizationChain
{
get { return finalize_handlers_chain; }
}
}
internal class HandlersChain
{
BaseRequestProcessorHandler chain;
public void ProcessRequestChain (MessageProcessingContext mrc)
{
if (chain != null)
chain.ProcessRequestChain (mrc);
}
public HandlersChain AddHandler (BaseRequestProcessorHandler handler)
{
if (chain == null) {
chain = handler;
}
else {
BaseRequestProcessorHandler current = chain;
while (current.Next != null)
current = current.Next;
current.Next = handler;
}
return this;
}
}
}
|