3

I'm trying to have Castle (3.0) inject constructor params into a WCF service, like this

ServiceHostBase clientServiceHost = new Castle.Facilities.WcfIntegration.DefaultServiceHostFactory()
.CreateServiceHost(typeof(IClientExchange).AssemblyQualifiedName, new Uri[0]);

However I get the following exception 'The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor.'

The service impl of type ClientExchange takes a constructor param of type IProviders

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class ClientExchangeService : ExchangeService, IClientExchange
{
    public ClientExchangeService(IProviders providers)
        : base(providers) { }
}

My windsor installer looks like this:

container.AddFacility<WcfFacility>()
.Register
(
  Component.For<IProviders>().Instance(Providers.DbInstance),
  Component.For<IClientExchange>().ImplementedBy<ClientExchangeService>(),
);

At the moment it seems like WCF is trying to new up the service without castle providing the dependency. Tried a few alternative examples out there but many are for previous versions of castle pre 3.0. I must be missing a hook somewhere? How do I tell WCF to defer construction responsibility to castle?

1 Answers1

4

I think this: how do i pass values to the constructor on my wcf service might be the answer to your problem. Or, for something more Windsor specific this might help: Dependency Injection in WCF Using Castle Windsor.

UPDATE

OK, so I think I have figured this out. First of all the problem is this attribute:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

If you do not specify that Windsor will be able to inject the dependencies into the constructor perfectly fine - with that it cannot.

From looking at the description of that attribute here I see that you want your service to be a singleton so since that is the default for Windsor you can simply remove that attribute and it should start working for you and behave as you expect.

There are two other lifestyles that you may be interested in that are specifically for WCF:

  • LifestylePerWcfOperation()
  • LifestylePerWcfSession()

(specify them in the normal place - more information is available here)

Incidentally, you do not have to do the ServiceHostBase stuff at all, instead you can use the AsWcfService extension method like so (personally I prefer this way of doing it):

container
    .AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
    .Register(
        Component
            .For<IProviders>()
            .Instance(Providers.DbInstance),
        Component
            .For<IClientExchange>()
            .ImplementedBy<ClientExchangeService>()
            .AsWcfService(new DefaultServiceModel()
                .AddEndpoints(WcfEndpoint
                    .BoundTo(new BasicHttpBinding())
                    .At("http://localhost:8000/ClientExchangeService"))));
Community
  • 1
  • 1
kmp
  • 9,895
  • 9
  • 66
  • 121