Search code examples
wcfduplex-channel

How can I extend WCF in the Callback direction?


I can attach an IParameterInspector using behaviors to each operation in the ClientRuntime and also to each operation in the DispatchRuntime on the service side. But it seems this only works from client to service.

I also want to be able to attach an IParameterInspector in the callbacks from service to client on both sides of the wire as above but I can't find any extensibility points to do this.

Any ideas?


Solution

  • This is a little obscure and does not appear to be all that well documented but you can customise both ends using standard WCF behavior capabilities.

    On the client, this attribute would make it happen.

    public class InspectorBehaviorAttribute : Attribute, IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            foreach (var item in clientRuntime.CallbackDispatchRuntime.Operations)
            {
                item.ParameterInspectors.Add(ParameterInspector.Instance);
            }
        }
    
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
        }
    
        public void Validate(ServiceEndpoint endpoint)
        {
        }
    }
    

    Simply apply this attribute on the class that implements your callback interface.

    On the server, it gets a little trickier. You need to hook up via the ApplyDispatchBehavior. In this case I have done it through a service behavior but the principal applies to OperationBehaviors and EndpointBehaviors as well.

    public class InspectorBehaviorAttribute : Attribute, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (var item in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>())
            {
                foreach (var ep in item.Endpoints)
                {
                    foreach (var op in ep.DispatchRuntime.CallbackClientRuntime.Operations)
                    {
                        op.ParameterInspectors.Add(ParameterInspector.Instance);
                    }
                }
            }
        }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
    }
    

    Again, simply apply this attribute to your service implementation to have your parameter inspector utilised for all callback operations.

    While these examples demonstrate hooking up IParameterInspector implementations, the same approach for all other WCF extension points can be used to customise callback channels at both the client and server.