3

Following the sample for compression by Microsoft. I have added the encoder, encoder factory, and binding element to my solution. The difference from their sample is that we do not register our endpoints via the config file (requirement), but instead use a custom Service Host Factory.

Service Host:

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
     ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);

     if (host.Description.Endpoints.Count == 0)
     {
          host.AddDefaultEndpoints();
     }

     host.Description.Behaviors.Add(new MessagingErrorHandler());      

     return host;
}

So what I have tried is to add a custom binding to my endpoint, but to register that endpoint with the binding it looks like I have to use the AddServiceEndpoint but that will require an interface which is unknown. I know I could get all the interfaces that the serviceType implements and do a getInterfaces()[0], but that seems to be an unsafe approach to me. So is there a way to register my endpoint with the custom binding and not know the interface, or is there a maybe a better approach that I should take.

My attempt at adding custom binding:

CustomBinding compression = new CustomBinding();
compression.Elements.Add(new GZipMessageEncodingBindingElement());
foreach (var uri in baseAddresses)
{
     host.AddServiceEndpoint(serviceType, compression, uri);//service type is not the interface and is causing the issue
}
DisplayName
  • 3,093
  • 5
  • 35
  • 42
  • Can you clarify why the interface is unknown? Perhaps I've misunderstood but it seems you're either defining the service endpoint (so should have the interface), or you're not - so shouldn't need to bind. – Basic May 17 '12 at 20:03
  • serviceType could have multiple interfaces so I do not which of those interfaces to assign to the endpoint – DisplayName May 17 '12 at 20:05
  • How are you registering one of the standard bindings, say `NetTcpBinding`, with your endpoint? – Bernard May 17 '12 at 20:39

1 Answers1

3

Your custom binding needs a transport binding element; currently you only have a message encoding binding element. You need to add probably a HttpTransportBindingElement to your custom binding as well:

CustomBinding compression = new CustomBinding(
    new GZipMessageEncodingBindingElement()
    new HttpTransportBindingElement());

As far as finding the interface from the service type, there's no built-in logic for that. The logic used in the WebServiceHostFactory is similar to the one shown below (this code goes 1 inheritance / implementation level deep, but you could in theory go deeper too.

    private Type GetContractType(Type serviceType) 
    { 
        if (HasServiceContract(serviceType)) 
        { 
            return serviceType; 
        } 

        Type[] possibleContractTypes = serviceType.GetInterfaces() 
            .Where(i => HasServiceContract(i)) 
            .ToArray(); 

        switch (possibleContractTypes.Length) 
        { 
            case 0: 
                throw new InvalidOperationException("Service type " + serviceType.FullName + " does not implement any interface decorated with the ServiceContractAttribute."); 
            case 1: 
                return possibleContractTypes[0]; 
            default: 
                throw new InvalidOperationException("Service type " + serviceType.FullName + " implements multiple interfaces decorated with the ServiceContractAttribute, not supported by this factory."); 
        } 
    } 

    private static bool HasServiceContract(Type type) 
    { 
        return Attribute.IsDefined(type, typeof(ServiceContractAttribute), false); 
    }
carlosfigueira
  • 85,035
  • 14
  • 131
  • 171